I have a series of post about deploying an ASP.NET Core application to different cloud providers which centered around clouds that provided a service that supported ASP.NET Core. The following are all the post in that vein if you are interested.
Google Cloud Platform
Amazon Web Services
Microsoft Azure
I was asked if I was going to do a post on deployment to DigitalOcean. While not in my original plan it was a good idea. The thing is DigitalOcean doesn’t have a service to support ASP.NET Core, but they do support Docker so this post is going to cover adding Docker support to a sample ASP.NET Core application. Look for a future post on how to deploy to DigitalOcean.
Docker
What is Docker? To quote Wikipedia:
Docker is a computer program that performs operating-system-level virtualization also known as containerization. It was first released in 2013 and is developed by Docker, Inc.
Docker is used to run software packages called “containers”. In a typical example use case, one container runs a web server and web application, while a second container runs a database server that is used by the web application. Containers are isolated from each other and use their own set of tools and libraries; they can communicate through well-defined channels. All containers use the same kernel and are therefore more lightweight than virtual machines. Containers are created from “images” which specify their precise contents. Images are often created by combining and modifying standard images downloaded from repositories.
Installing Docker
Head to this link and click the Get Docker link to download the installer. After the install is complete you will have to log out and back in. When I logged back in I got a message about Hyper-V not being enabled.
After logging back in I then got the following message about hardware-assisted virtualization not being enabled.
After tweaking my BIOS settings and logging back in I was greeted by the Docker welcome screen.
Open a command prompt and run the following command.
docker run hello-world
You should output that starts with the following if your installation is working.
Hello from Docker!
This message shows that your installation appears to be working correctly.
Sample Application
This is the same as in the cloud series, but am including it in case you missed that post. The sample application that we will be deploying is the basic Razor Pages applications created using the .NET CLI. The following commands are what I used to create the application, create a solution, and add the project to the solution. I ran all these commands in a CloudSample
directory.
dotnet new razor --no-https
dotnet new sln
dotnet sln add CloudSample.csproj
Add Docker Support
Open the solution created above in Visual Studio and right-click the project and select Add > Docker Support.
Next, you will have the select the OS you want to target.
This will add the following four files to your project.
docker-compose.dcproj
docker-compose.override.yml
docker-compose.yml
Dockerfile
The process will also change your project to start in Docker when you hit run from in Visual Studio.
Publishing
In order to publish we need an account with a registry that we want to publish to. There are multiple options, but I am going to be using Docker Hub. Go to Docker Hub and sign up for an account. After you get signed in on your Repositories tab click Create Repository.
On the next page enter a name for your repository, select if you want it to be private or public and click Create. I’m using the name TestRepository and making it private.
Now that we have a Docker Hub account hope back to Visual Studio and right-click on your project and select Publish.
On the next on the dialog select the Container Registry option and then Docker Hub. Then click the Publish button.
On the next dialog enter your username and password for Docker Hub and click Save.
After saving Visual Studio will build and publish the application to Docker Hub.
Issues
If you get luck the above will work for you. I hit a couple of issues that made the above fail for some reason. The following is the first error I got.
Error: Service ‘cloudsample’ failed to build: The command ‘/bin/sh -c dotnet restore /CloudSample.csproj’ returned a non-zero code: 1
After some digging, I found this GitHub issue. The gist of the fix is to change the following in the DockerFile.
Before:
RUN dotnet restore /CloudSample.csproj
After:
RUN dotnet restore -nowarn:msb3202,nu1503 -p:RestoreUseSkipNonexistentTargets=false
The above fixed the build when in release mode, but publish still failed on me with the following error when the tools were attempting to tag the image.
System.Exception: Running the docker.exe tag command failed.
at Microsoft.VisualStudio.Web.Azure.Publish.ContainerRegistryProfileVisual.DockerTag(ProcessStartInfo startInfo, String serverUrlString)
at Microsoft.VisualStudio.Web.Azure.Publish.ContainerRegistryProfileVisual.<PostPublishAsync>d__24.MoveNext()
— End of stack trace from previous location where exception was thrown —
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.ApplicationCapabilities.Publish.ViewModel.ProfileSelectorViewModel.<RunPublishTaskAsync>d__116.MoveNext()
I haven’t found a way to get around this issue. I ended up using the Docker CLI to push my image. This takes a few steps. First, use the following command to log in.
docker login
Next, use the docker images
command to find the image you are trying to push. In my case, it was the image with ID f83e5adab340. When the ID we can now use the following command to tag the image.
docker tag f83e5adab340 elanderson/testrepository
It is important that the image is tagged with the name of the repository it is going to be pushed to. Finally, run the following command to push the image with the specified tag into your repository.
docker push elanderson/testrepository
Wrapping Up
The teams at Microsoft have made adding Docker support to an existing project super simple. Docker is something that I have had a surface level awareness of for a while, and I am looking forward to trying an actual deployment to see how that works with DigitalOcean.