Docker file for rhino.compute.exe

@will

Hello,

we’re trying to run compute.geometry in a docker container on a windows server. We have got it to work for compute.geometry using the docker file in the rhino compute repo compute.rhino3d/Dockerfile at 7.x · mcneel/compute.rhino3d · GitHub

But when we change the docker file to copy over the whole release foler and run rhino.compute.exe in the container like this:

COPY --from=builder ["/src/bin/Release/*", "/app"]
WORKDIR /app
ENV RHINO_COMPUTE_URLS="http://+:80"
EXPOSE 80
CMD ["rhino.compute.exe"]

we get the following: A fatal error occurred. The required library hostfxr.dll could not be found.

So this is an error that occurs during runtime. We’re probably missing something in out docker file, but we haven’t been able to find a dedicated docker file for rhino.compute.exe. Has anyone else had the same issue?

Erik

Try modifying the Dockerfile to install .NET 5.0 instead of (or as well as) .NET 4.8.

Or, you could try building rhino.compute.exe as a self-contained executable like we do to distribute Hops.

Hello Will!

Thanks for your fast reply. We had a look at what you had done in hops and understood that we needed to use publish instead of build to create a self contained .exe. The thing is that this also messes up the build folders a bit so we needed to do some other tweaks to the docker file as well. I’ll paste our working docker file here, but maybe it would be a good idea to include something similar in the repo as well.

BR
Erik

# escape=`

# see https://discourse.mcneel.com/t/docker-support/89322 for troubleshooting

# NOTE: use 'process' isolation to build image (otherwise rhino fails to install)

### builder image
FROM mcr.microsoft.com/dotnet/sdk:5.0 as builder

# copy everything, restore nuget packages and build app
COPY src/ ./src/
RUN dotnet publish -c Release -r win10-x64 --self-contained true src/compute.sln

### main image
# tag must match windows host for build (and run, if running with process isolation)
# e.g. 1903 for Windows 10 version 1903 host
FROM mcr.microsoft.com/windows:1809

# install .net 4.8 if you're using the 1809 base image (see https://git.io/JUYio)
# comment this out for 1903 and newer
RUN curl -fSLo dotnet-framework-installer.exe https://download.visualstudio.microsoft.com/download/pr/7afca223-55d2-470a-8edc-6a1739ae3252/abd170b4b0ec15ad0222a809b761a036/ndp48-x86-x64-allos-enu.exe `
    && .\dotnet-framework-installer.exe /q `
    && del .\dotnet-framework-installer.exe `
    && powershell Remove-Item -Force -Recurse ${Env:TEMP}\*

# install rhino (with “-package -quiet” args)
# NOTE: edit this if you use a different version of rhino!
# the url below will always redirect to the latest rhino 7 (email required)
# https://www.rhino3d.com/download/rhino-for-windows/7/latest/direct?email=EMAIL
RUN curl -fSLo rhino_installer.exe https://www.rhino3d.com/download/rhino-for-windows/7/latest/direct?email=EMAIL `
    && .\rhino_installer.exe -package -quiet `
    && del .\rhino_installer.exe

# (optional) use the package manager to install plug-ins
# RUN ""C:\Program Files\Rhino 7\System\Yak.exe"" install jswan

# copy compute app to image
COPY --from=builder ["/src/dist", "/app"]
WORKDIR /app

# bind rhino.compute to port 5000
EXPOSE 5000

# uncomment to build core-hour billing credentials into image (not recommended)
# see https://developer.rhino3d.com/guides/compute/core-hour-billing/
ENV RHINO_TOKEN=TOKEN

CMD ["rhino.compute/rhino.compute.exe"]

Thanks for sharing!

I haven’t had chance to try the new rhino.compute.exe setup in Docker. I also wonder if there are other mechanisms for scaling compute.geometry.exe containers based on the number of requests.

p.s. You should be able to replace this…

RUN mkdir app\rhino.compute
RUN mkdir app\compute.geometry
COPY --from=builder ["/src/bin/Release/rhino.compute/win10-x64/", "/app/rhino.compute"]
COPY --from=builder ["/src/bin/Release/compute.geometry/win10-x64/", "/app/compute.geometry"]

… with this…

COPY --from=builder ["/src/dist", "/app"]
1 Like

No problems!

Thanks for your suggestion, we didn’t notice the /dist but I’ll edit my response to make it easier for people to copy the solution.

BR
Erik

Hello @erikforsberg95 and @will

I am trying to host rhino.compute on GKE, and was able to build a docker image with the above Dockerfile (thanks Eric). However, it can’t take any traffic from outside the container to rhino.compute. When I curl against localhost:5000 inside the container, it works fine, but we have HA set up with Service Discovery and LB and our backends show unhealthy all the time.

Any ideas?

PS: I’m new to Windows containers and .Net. Any help is appreciated

Hi @user335,

happy to hear that the docker file helped. Unfortunately, I’ve ran into the same problem with routing outside tragic into the container so we decided to run the compute instance directly on the windows server for now. It’s not a perfect solution but it does the job. We’re still looking (passively) for a better solution and I’ll post here if I find one. Maybe @will have some updates regarding this?

Good luck with the project.
Erik

You could try adding ENV ASPNETCORE_URLS http://*:5000 to tell the web server to listen on all interfaces (not just localhost). I added the RHINO_COMPUTE_URLS environment variable to compute.geometry for the same purpose, but ASP.NET 5 projects have their own way of doing this.

Thanks @will. It resolved the issue. I will paste full Dockerfile here.

# escape=`

# see https://discourse.mcneel.com/t/docker-support/89322 for troubleshooting

# NOTE: use 'process' isolation to build image (otherwise rhino fails to install)

### builder image
FROM mcr.microsoft.com/dotnet/sdk:5.0 as builder

# copy everything, restore nuget packages and build app
COPY src/ ./src/
RUN dotnet publish -c Release -r win10-x64 --self-contained true src/compute.sln

### main image
# tag must match windows host for build (and run, if running with process isolation)
# e.g. 1903 for Windows 10 version 1903 host
FROM mcr.microsoft.com/windows:1809

#Copy the fonts and font install script
COPY fonts/* fonts/
COPY InstallFont.ps1 .

#Run font install scriptin powershell
RUN powershell -ExecutionPolicy Bypass -Command .\InstallFont.ps1

# install .net 4.8 if you're using the 1809 base image (see https://git.io/JUYio)
# comment this out for 1903 and newer
RUN curl -fSLo dotnet-framework-installer.exe https://download.visualstudio.microsoft.com/download/pr/7afca223-55d2-470a-8edc-6a1739ae3252/abd170b4b0ec15ad0222a809b761a036/ndp48-x86-x64-allos-enu.exe `
    && .\dotnet-framework-installer.exe /q `
    && del .\dotnet-framework-installer.exe `
    && powershell Remove-Item -Force -Recurse ${Env:TEMP}\*

# install rhino (with “-package -quiet” args)
# NOTE: edit this if you use a different version of rhino!
# the url below will always redirect to the latest rhino 7 (email required)
# https://www.rhino3d.com/download/rhino-for-windows/7/latest/direct?email=EMAIL
RUN curl -fSLo rhino_installer.exe https://www.rhino3d.com/download/rhino-for-windows/7/latest/direct?email=<email> `
    && .\rhino_installer.exe -package -quiet `
    && del .\rhino_installer.exe

# (optional) use the package manager to install plug-ins
# RUN ""C:\Program Files\Rhino 7\System\Yak.exe"" install jswan

# copy compute app to image
COPY --from=builder ["/src/dist", "/app"]
WORKDIR /app

# bind rhino.compute to port 5000
ENV ASPNETCORE_URLS="http://*:5000"
EXPOSE 5000

# uncomment to build core-hour billing credentials into image (not recommended)
# see https://developer.rhino3d.com/guides/compute/core-hour-billing/
#ENV RHINO_TOKEN=<yourtokenhere>

CMD ["rhino.compute/rhino.compute.exe"]
2 Likes

Wow, thanks for this! I’ll give it a try and post if it works or if I have any problems.

Erik

Hello,

I tried pulling the latest Dockerfile and building locally on my windows machine via docker build --pull --isolation process -t rhino-compute . However I get blocked on step 3/14 with an error message of

encountered an error during hcsshim::System::Start: failure in a Windows system call: The virtual machine or container exited unexpectedly. (0xc0370106)

I ran into an issue on step 2/14 till I uninstalled box drive which I found mentioned in another post. Curious is there another step required for building the compute app? I tried following what this post suggested, but that didn’t seem to change anything for me.

For context I am hoping to get a docker container with rhino.compute built to ultimately deploy to AWS ECS so as we make updates to the various grasshopper networks we don’t have to manually spin up instances again.

Any help on this would be really appreciated, thank you!

@hantic Sorry for the delay. Are you still getting blocked? What Windows version are you running? I just spun up a VM with Windows Server 2019 and it worked straightaway. Also, I don’t know if you’ve seen it, but our preferred method for deploying Rhino.Compute for a production environment is described in this guide. I believe that setup might be a little easier and it’s been tested a lot so I can help troubleshoot if you run into any issues.

Hi Andy,

Sorry for my delay :slight_smile: I got everything working on my end. Thank you for following up!

Hello @will

Sorry for opening an old thread. Recently we started facing issues with building rhino.compute docker image. I tried with latest 7.X code from McNeel repo and the following dockerfile:

# escape=`

# see https://discourse.mcneel.com/t/docker-support/89322 for troubleshooting

# NOTE: use 'process' isolation to build image (otherwise rhino fails to install)

### builder image
FROM mcr.microsoft.com/dotnet/sdk:5.0 as builder

# copy everything, restore nuget packages and build app
COPY src/ ./src/
#RUN dotnet build -c Release src/compute.sln
RUN dotnet publish -c Release -r win10-x64 --self-contained true src/compute.sln

### main image
# tag must match windows host for build (and run, if running with process isolation)
# e.g. 1903 for Windows 10 version 1903 host
FROM mcr.microsoft.com/windows:1809

#Copy the fonts and font install script
COPY fonts/* fonts/
COPY InstallFont.ps1 .

#Run font install scriptin powershell
RUN powershell -ExecutionPolicy Bypass -Command .\InstallFont.ps1

#Copy and extract Pufferfish plugin
COPY plugins/* plugins/

#RUN powershell Expand-Archive -Path ./test_plugins.zip -DestinationPath .

# install .net 4.8 if you're using the 1809 base image (see https://git.io/JUYio)
# comment this out for 1903 and newer
RUN curl -fSLo dotnet-framework-installer.exe https://download.visualstudio.microsoft.com/download/pr/7afca223-55d2-470a-8edc-6a1739ae3252/abd170b4b0ec15ad0222a809b761a036/ndp48-x86-x64-allos-enu.exe `
    && .\dotnet-framework-installer.exe /q `
    && del .\dotnet-framework-installer.exe `
    && powershell Remove-Item -Force -Recurse ${Env:TEMP}\*

# install rhino (with “-package -quiet” args)
# NOTE: edit this if you use a different version of rhino!
# the url below will always redirect to the latest rhino 7 (email required)
# https://www.rhino3d.com/download/rhino-for-windows/7/latest/direct?email=EMAIL
RUN curl -fSLo rhino_installer.exe https://www.rhino3d.com/download/rhino-for-windows/7/latest/direct?email=nikhil@jewlr.com `
    && .\rhino_installer.exe -package -quiet `
    && del .\rhino_installer.exe

#Create a libraries directory for the plugin and copy .gha file
RUN powershell mkdir C:\Users\ContainerAdministrator\AppData\Roaming\Grasshopper\Libraries

#RUN powershell Copy-Item -Path .\plugins\Pufferfish.gha -Destination "C:\Users\ContainerAdministrator\AppData\Roaming\Grasshopper\Libraries\Pufferfish.gha" `
RUN powershell Copy-Item -Path .\plugins\Conductor.gha -Destination "C:\Program` Files\Rhino` 7\Plug-ins\Grasshopper\Components\Conductor.gha" `
    && powershell Copy-Item -Path .\plugins\DefaultValue.gha -Destination "C:\Program` Files\Rhino` 7\Plug-ins\Grasshopper\Components\DefaultValue.gha" `
    && powershell Copy-Item -Path .\plugins\Jewlr.gha -Destination "C:\Program` Files\Rhino` 7\Plug-ins\Grasshopper\Components\Jewlr.gha"

#Copy config files
RUN powershell mkdir C:\Users\ContainerAdministrator\config
COPY config/* C:\Users\ContainerAdministrator\config\


# copy compute app to image
COPY --from=builder ["/src/dist", "/app"]

# after facing an error about missing appsettings.json at c:\app, I added this line
COPY --from=builder ["/src/dist/rhino.compute/appsettings.json", "/app"]
WORKDIR /app



# bind rhino.compute to port 5000
ENV ASPNETCORE_URLS="http://*:5000"
EXPOSE 5000

# uncomment to build core-hour billing credentials into image (not recommended)
# see https://developer.rhino3d.com/guides/compute/core-hour-billing/
#ENV RHINO_TOKEN=""

CMD ["rhino.compute/rhino.compute.exe","--idlespan=1800"]

When I run the container, I face this error:

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at Rhino.Runtime.InProcess.RhinoCore.InternalStartup(Int32 argc, String[] argv, StartupInfo& info, IntPtr hostWnd)
   at Rhino.Runtime.InProcess.RhinoCore..ctor(String[] args, WindowStyle windowStyle, IntPtr hostWnd)
   at compute.geometry.OwinSelfHost.Start(HostControl hctrl) in C:\src\compute.geometry\Program.cs:line 115
   at Topshelf.Builders.ControlServiceBuilder`1.ControlServiceHandle.Start(HostControl hostControl)
   at Topshelf.Hosts.ConsoleRunHost.Run()
   at Topshelf.HostFactory.Run(Action`1 configureCallback)
   at compute.geometry.Program.Main(String[] args) in C:\src\compute.geometry\Program.cs:line 40

We were on a call with Andy and Steve on Friday, but we couldn’t figure out the Docker related issues. Any help is appreciated.

TIA.

I got the same error with this docker file.

@user335, @Yash_Babariya, any luck with this issue?
I’m also getting an AccessViolationException on RhinoCore.InternalStartup.

@visose Still, I have not gotten a solution for this error.

How do I get the Rhino Compute API key while running Docker? I need to connect to the API using the API key.

Your API key should be stored as an environment variable… but again, I don’t know much about your Docker configuration so I don’t know if that is the case.

1 Like