How do you write a Dockerfile for an ASP.NET Core app?

Published: Thursday 2 January 2025

A Dockerfile allows you to build and publish an ASP.NET Core application to a Docker container.

Dockerize an ASP.NET Core Web API

This tutorial will show you how to write a Dockerfile for an ASP.NET Core Web API. The Web API has two class libraries referenced to it. An application and an infrastructure class library.

Libraries

  • RoundTheCode.DockerSample.Application (Located in the Libraries/RoundTheCode.DockerSample.Application folder)
  • RoundTheCode.DockerSample.Infrastructure (Located in the Libraries/RoundTheCode.DockerSample.Infrastructure folder)

Web API

  • RoundTheCode.DockerSample.WebApi(Located in the Web/RoundTheCode.DockerSample.WebApi folder)

The Dockerfile

In the ASP.NET Core Web API folder, we are going to create a new file called Dockerfile. From there, we are going to add some arguments.

The arguments

We are going to specify the .NET version and the build configuration a number of times within Dockerfile. Therefore, we are going to reference them as arguments at the beginning of the file.

# Dockerfile
ARG DOTNET_VERSION=9.0
ARG BUILD_CONFIGURATION=Release

The build image

In-order to build and publish the Web API, we need to create a stage from the image. As we want to use the .NET SDK to do this, we need to have an image with the SDK installed.

Fortunately, Microsoft has an artifact registry which allows us to download the image with the .NET SDK installed.

C# coding challenges

C# coding challenges

Our online code editor allows you to compile the answer.

To download the .NET SDK, we get the image from mcr.microsoft.com/dotnet/sdk:$DOTNET_VERSION and replace $DOTNET_VERSION with the version we want to use.

We specify where to get the image by using the FROM command. In-addition, we can give the stage an alias. We have given it an alias of build.

# Dockerfile
ARG DOTNET_VERSION=9.0
ARG BUILD_CONFIGURATION=Release

FROM mcr.microsoft.com/dotnet/sdk:$DOTNET_VERSION AS build

Copying the files

Next, we want to copy the files that we need from our machine into the build stage. To do that, we change the build stage's work directory to /src and then copy the files and folders from our machine into the /src folder of the build stage. As we have three projects that are dependent on it, we need to copy all of them into the build stage.

# Dockerfile
ARG DOTNET_VERSION=9.0
ARG BUILD_CONFIGURATION=Release

FROM mcr.microsoft.com/dotnet/sdk:$DOTNET_VERSION AS build

WORKDIR /src
COPY ["Libraries/RoundTheCode.DockerSample.Application/", "Libraries/RoundTheCode.DockerSample.Application/"]
COPY ["Libraries/RoundTheCode.DockerSample.Infrastructure/", "Libraries/RoundTheCode.DockerSample.Infrastructure/"]
COPY ["Web/RoundTheCode.DockerSample.WebApi/", "Web/RoundTheCode.DockerSample.WebApi/"]

Restore, build and publish the ASP.NET Core Web API

Afterwards, we want to restore, build and publish the ASP.NET Core Web API. To do that, we run the relevant dotnet command, add the csproj file and add some parameters.

When building and publishing the Web API, we want to make sure that we build it using the release configuration and also to specify the output folder.

When publishing the Web API, we can specify the runtime version. We have specified linux-musl-x64 which is more of a lightweight distribution of Linux which will help with the overall file size of the Docker container.

# Dockerfile
ARG DOTNET_VERSION=9.0
ARG BUILD_CONFIGURATION=Release

FROM mcr.microsoft.com/dotnet/sdk:$DOTNET_VERSION AS build

WORKDIR /src
COPY ["Libraries/RoundTheCode.DockerSample.Application/", "Libraries/RoundTheCode.DockerSample.Application/"]
COPY ["Libraries/RoundTheCode.DockerSample.Infrastructure/", "Libraries/RoundTheCode.DockerSample.Infrastructure/"]
COPY ["Web/RoundTheCode.DockerSample.WebApi/", "Web/RoundTheCode.DockerSample.WebApi/"]

WORKDIR /src/Web/RoundTheCode.DockerSample.WebApi
RUN dotnet restore "./RoundTheCode.DockerSample.WebApi.csproj"
RUN dotnet build "./RoundTheCode.DockerSample.WebApi.csproj" -c "$BUILD_CONFIGURATION" -o /app/build

RUN dotnet publish "./RoundTheCode.DockerSample.WebApi.csproj" -c "$BUILD_CONFIGURATION" -o /app/publish -r linux-musl-x64

Run the Docker image

So far, we've used the .NET SDK image to build and publish the application. But the .NET SDK image has a very large file size, so we don't want to run the application using that image.

Instead, we want to run the published files from the .NET runtime image.

The Microsoft Artifact Registry website has an image with the ASP.NET Core Runtime which allows us to do just that. We get the image from mcr.microsoft.com/dotnet/aspnet:$DOTNET_VERSION and replace $DOTNET_VERSION with the version we wish to use.

Once again, we specify where to get the image by using the FROM command. For the runtime stage, we've given it an alias of run.

# Dockerfile
ARG DOTNET_VERSION=9.0
ARG BUILD_CONFIGURATION=Release

FROM mcr.microsoft.com/dotnet/sdk:$DOTNET_VERSION AS build

WORKDIR /src
COPY ["Libraries/RoundTheCode.DockerSample.Application/", "Libraries/RoundTheCode.DockerSample.Application/"]
COPY ["Libraries/RoundTheCode.DockerSample.Infrastructure/", "Libraries/RoundTheCode.DockerSample.Infrastructure/"]
COPY ["Web/RoundTheCode.DockerSample.WebApi/", "Web/RoundTheCode.DockerSample.WebApi/"]

WORKDIR /src/Web/RoundTheCode.DockerSample.WebApi
RUN dotnet restore "./RoundTheCode.DockerSample.WebApi.csproj"
RUN dotnet build "./RoundTheCode.DockerSample.WebApi.csproj" -c "$BUILD_CONFIGURATION" -o /app/build

RUN dotnet publish "./RoundTheCode.DockerSample.WebApi.csproj" -c "$BUILD_CONFIGURATION" -o /app/publish -r linux-musl-x64

FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_VERSION AS run

In the run stage, we set the working directory to /app. In the build stage, we published the application into the /app/publish folder. We copy these files into the run stage and then set the entry point to run dotnet RoundTheCode.DockerSample.WebApi.dll. This will run the Web API in the Docker container. 

Here is the full Dockerfile:

# Dockerfile
ARG DOTNET_VERSION=9.0
ARG BUILD_CONFIGURATION=Release

FROM mcr.microsoft.com/dotnet/sdk:$DOTNET_VERSION AS build

WORKDIR /src
COPY ["Libraries/RoundTheCode.DockerSample.Application/", "Libraries/RoundTheCode.DockerSample.Application/"]
COPY ["Libraries/RoundTheCode.DockerSample.Infrastructure/", "Libraries/RoundTheCode.DockerSample.Infrastructure/"]
COPY ["Web/RoundTheCode.DockerSample.WebApi/", "Web/RoundTheCode.DockerSample.WebApi/"]

WORKDIR /src/Web/RoundTheCode.DockerSample.WebApi
RUN dotnet restore "./RoundTheCode.DockerSample.WebApi.csproj"
RUN dotnet build "./RoundTheCode.DockerSample.WebApi.csproj" -c "$BUILD_CONFIGURATION" -o /app/build

RUN dotnet publish "./RoundTheCode.DockerSample.WebApi.csproj" -c "$BUILD_CONFIGURATION" -o /app/publish -r linux-musl-x64

FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_VERSION AS run
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT [ "dotnet", "RoundTheCode.DockerSample.WebApi.dll" ]

Build and run the Docker container

With the Dockerfile created, we can now build and run the Docker container. But first, we need to ensure that the Docker CLI is installed.

If you're a Windows user, you can either install Docker Desktop or Rancher Desktop onto your machine as both include the Docker CLI. If you're using Docker Desktop on Windows, you'll need to ensure that Windows Subsystem for Linux (WSL) is installed on your machine.

To do that, you go into Control Panel and Programs and Features. Select Turn Windows features on or off on the left-hand side and select Windows Subsystem for Linux if it's not already ticked. This will install it for you.

Build the Dockerfile

To build the Dockerfile, we open up a terminal window and change to the directory where Dockerfile is. From there, we can run docker build and specify some parameters. The -f parameter is the name of the docker file that we are building which will be Dockerfile and the -t parameter is the tag name. The tag name can be anything we want, and we can specify a version number by appending a : to it.

We also specify "../../" to the end of the docker build command. The reason is that we want to run the docker command from two folders back as that's where the class libraries are located and we need to be able to copy them.

docker build -f "Dockerfile" -t roundthecode.dockersample.webapi:1.0 "../../"

Run the Dockerfile

If the ASP.NET Core version is .NET 8 or later, the Docker container will run the ASP.NET Core app on port 8080 by default. We want to use port forwarding so the ASP.NET Core application runs on port 38080 on our machine. To do that, we can specify the -p parameter when calling the docker run command. We specify the port for running the app on our machine and use a : to separate the port number from the Docker container. We then specify the tag name that we wish to run.

docker run -p 38080:8080 roundthecode.dockersample.webapi:1.0

See it for yourself

Watch our video where we talk you through each of the steps to create, build and run an ASP.NET Core application from a Docker container.

You can also download the code example which includes the Dockerfile so you can try and run it for yourself.