In my previous post, I showcased how to get started with docker and building the first dotnet core docker image. In this post, I will show how we can easily create a docker image for an core mvc based website. I will be using Mac OS X, Docker on Mac, VisualStudio Code on Mac for this demo, the steps that I showcase here should work as is in windows as well (provided you install the windows counterpart for each of them)

Step 1 : Scaffold a new core mvc website

This can be done by using the dotnet CLI. Run the below command

dotnet new -t web
Created new C# project in /Users/swami/Projects/DotnetCore/aspnet-core-mvc-demo.

To make sure the app works fine, run the below commands and ensure the website is browsable

dotnet restore
dotnet run

Project aspnet-core-mvc-demo (.NETCoreApp,Version=v1.0) will be compiled because expected outputs are missing
Compiling aspnet-core-mvc-demo for .NETCoreApp,Version=v1.0
Compilation succeeded.
0 Warning(s)
0 Error(s)
Time elapsed 00:00:02.1554545
info: Microsoft.Extensions.DependencyInjection.DataProtectionServices[0]
User profile is available. Using '/Users/swami/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
Hosting environment: Production
Content root path: /Users/swami/Projects/DotnetCore/aspnet-core-mvc-demo
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Step 2 : Add Dockerfile

Dockerfile is the key component that is used to build docker images. All the necessary steps and the commands to be run, have to be put inside this file. Create a file named Dockerfile at the root directory of the app. To know the various commands that are allowed inside the docker file refer their documentation. Also to get nice code snippets for the docker commands, install Docker Tools for VS Code extension. To build a very basic core image, mention the below steps in Dockerfile

FROM microsoft/dotnet:latest
COPY /app /app
ENTRYPOINT ["dotnet","aspnet-core-mvc-demo.dll"]

FROM microsoft/dotnet:latest – tells the docker daemon to build this image from the microsoft dotnet latest image

WORKDIR /app – to set the working directory for the app

COPY /app /app – to copy the /app directory from local machine to the image

ENV ASPNETCORE_URLS http://*:8000 – to specify dotnet core to host this app and run under the port 8000

EXPOSE 8000 – to expose the port 8000 from the image. Without this, we wouldn’t be able to access the application running in the port 8000. Note that, it doesn’t mean when we run the image, this port will be mapped automatically to the host machine’s port. We will get to that later in the next step when we run the image.

ENTRYPOINT ["dotnet","aspnet-core-mvc-demo.dll"] – to specify what’s the entry point for this image, i.e, when this image is run by the docker what should it be doing. In this case, we are running the website using the dotnet cli command. Note that, incase you created a new project within a different folder name, you should be specifying that name.dll in the entry point here.

Step 3 : Build the docker image

To build the docker image, run the following command

dotnet publish -c Release -o app

docker build -t aspnet-core-mvc-demo .

dotnet publish command is used to publish the output of the application to /app folder and that’s what gets copied inside the image.

docker build command works on the context, in this case I have set the context to current working directory by specifying . docker build command gets executed by the docker daemon process, so we should be very cautious in specifying the context properly otherwise all the contents present within the folder specified as context will be sent to the daemon process.

-t aspnet-core-mvc-demo is specified to give a meaningful tag to the image we are creating. The output of the above command should look like below:

Sending build context to Docker daemon 36.37 MB
Step 1 : FROM microsoft/dotnet:latest
---> 9037d65411f1
Step 2 : WORKDIR /app
---> Running in 81c9cb6dbe27
---> dde7f7886361
Removing intermediate container 81c9cb6dbe27
Step 3 : COPY /app /app
---> 068684efab98
Removing intermediate container a29704b9ed5a
Step 4 : ENV ASPNETCORE_URLS http://*:8000
---> Running in 2c3f59efffd1
---> 34a8327f9773
Removing intermediate container 2c3f59efffd1
Step 5 : EXPOSE 8000
---> Running in 95868e516c32
---> 2ed4c9a67cd0
Removing intermediate container 95868e516c32
Step 6 : ENTRYPOINT dotnet aspnet-core-mvc-demo.dll
---> Running in d83da56ffc64
---> 918275017b29
Removing intermediate container d83da56ffc64
Successfully built 918275017b29

Running the below command should display the image we just built.

docker images

REPOSITORY                           TAG                  IMAGE ID            CREATED             SIZE

aspnet-core-mvc-demo                 latest               0166bb16892e        54 seconds ago      275 MB

Step 4 : Run the docker image

To run the image, execute the below command

docker run -p 8000:8000 aspnet-core-mvc-demo

info: Microsoft.Extensions.DependencyInjection.DataProtectionServices[0]
User profile is available. Using '/root/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
Hosting environment: Production
Content root path: /app
Now listening on: http://*:8000
Application started. Press Ctrl+C to shut down.

Note the use of arguments -p 8000:8000 – this is what will map the port 8000 within the container to the local machine’s port 8000. If you try running the image without this port mapping, you wouldn’t be able to access the application. Open the browser and try hitting the url http://localhost:8000 and you should be seeing the same output as what you saw in the first step.

Congratulations! You just built the docker image for core mvc web app! 🙂 More on building images for web app with multiple services in a future post.