Using Docker With .NET Core

Docker is an incredibly popular software container platform. If you don't know what it is read more about it here.

Docker for Windows

I'm running Windows 10 and using Docker for Windows. The most important thing to mention is that as of writing this Docker for Windows only runs on 64 bit Windows 10 Pro, Enterprise and Education. Check the Docker for Windows page for the full requirements.

Docker for Windows is great because it lets me work with both Linux and Windows containers. Running in Linux container mode I can run all the Linux-based images from Docker Hub, etc. Docker for Windows also lets me work with Windows Containers, but for the rest of this post I'll be working with Linux containers.

Get Your .NET Core API Containerized

I'll assume you have a Web API project with at least one endpoint already.

All About That Dockerfile

In your root source directory add a file Dockerfile. This will be the file that contains the instructions for Docker on how to build your image. I'll give a quick rundown to get you started here, but you can also check out the Dockerfile reference docs for more info.

Dockerfile Location

src/
  |-- Controllers
  |-- Models
  |-- Program.cs
  |-- Startup.cs
  |-- Dockerfile        # Keep your Dockerfile with your source code
.gitignore
readme.md

Now that you've got a Dockerfile, let's give it some instructions.

FROM microsoft/aspnetcore:1.1
WORKDIR /app
COPY dist ./
ENTRYPOINT ["dotnet", "sample-api.dll"]

FROM

The FROM instruction sets the base image for your container. Here we're pulling the Microsoft ASP.NET Core image which contains the .NET Core runtime we'll need to run our API. The :1.1 after aspnetcore is a tag indicating we want to use the .NET Core 1.1 image.

WORKDIR

The WORKDIR instruction sets the working directory for our later instructions in the Dockerfile. WORKDIR will be created even if it isn't used, and will be relative to any previous WORKDIR instructions.

COPY

The COPY instruction copies contents from a "source" and adds them to the the container in the path "destination". The Dockerfile shown above is in this format: COPY SOURCE DESTINATION, so we're copying contents from our dist folder to the container's filesystem path ./.

ENTRYPOINT

Finally, the ENTRYPOINT allows us to set that our container will be executable. Later when we docker run it will essentially start our container and run dotnet sample-api.dll inside of it.

Turn .NET Core Source Code Into A Docker Image

Before building running docker build you'll need to dotnet publish your project to the dist directory we've specified in the Dockerfile. For more info on dotnet publish check out my .NET Core CLI Post.

Once you've got compiled code and a Dockerfile, go to the command line and build the image.

docker build -t sample-api .

This is the docker build command (docs) and it will build our image based on the instructions in the Dockerfile found in the current directory and then tag it "sample-api".

Sample Output
C:\src> docker build -t sample-api .
Sending build context to Docker daemon 16.28 MB
Step 1/4 : FROM microsoft/aspnetcore:1.1
 ---> 325aeff6afd5
Step 2/4 : WORKDIR /app
 ---> Using cache
 ---> f83788bdcacc
Step 3/4 : COPY dist ./
 ---> Using cache
 ---> e1b5887e9bde
Step 4/4 : ENTRYPOINT dotnet sample-api.dll
 ---> Using cache
 ---> 88801a46b43d
Successfully built 88801a46b43d
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

Running Your .NET Core API Docker Image

Now that we've built our image we can run it. Let's run docker from the command line:

docker run -p 80:80 sample-api

Docker run docs can be found here.

For our command the option -p 80:80 is mapping the container port 80 to the container host port 80, so now when you browse to 127.0.0.1 you should now be able to see get a response from your web api (assuming you have a route that responds to that particular GET request).

The sample-api option is telling Docker which image to run.

When you execute docker run you'll see output like this telling you that your containerized API is now running:

Sample Output

c:\src>docker run -p 80:80 sample-api
Hosting environment: Production
Content root path: /app
Now listening on: http://*:80
Application started. Press Ctrl+C to shut down.

.dockerignore

One last thing to mention is the .dockerignore file. This optional file will exclude files and directories that you might not want in your image. This can help keep your images smaller and ensure they don't contain any sensitive data. Read more about the .dockerignore file here.