Problem
How to containerize ASP.NET Core 2.0 web application and deploy to Azure Web App.
Solution
Install Docker.
Create a Docker Hub account (free).
Create Azure subscription (free, gives you credit to play).
Create a simple ASP.NET Core 2.0 web application. Add a file named Dockerfile
with following contents:
# Build Stage
FROM microsoft/aspnetcore-build as build-env
WORKDIR /source
COPY . .
RUN dotnet restore
RUN dotnet publish -o /publish --configuration Release
# Publish Stage
FROM microsoft/aspnetcore
WORKDIR /app
COPY --from=build-env /publish .
ENTRYPOINT ["dotnet", "Fiver.Asp.Docker.Basic.dll"]
Note: replace “Fiver.Asp.Docker.Basic” with the name of your solution.
Add another file named docker-compose.yml
with following contents:
version: '3.3'
services:
api:
build:
context: .
dockerfile: Dockerfile
image: fiver/basic
ports:
- "8080:80"
Note: replace “fiver/basic” with the name you want to give to your image.
My solution looks like this:
Open command line to the root of your project and run below to build and run the application in a container:
docker-compose up
Browse the application to ensure it works locally, using URL localhost:8080:
Run the command to create a tag for the image, which is required to upload image to Docker Hub:
docker tag fiver/basic naushadt25/fiver
Then login to Docker Hub:
docker login -u [username] -p [password]
Next push the image to Docker Hub:
docker push naushadt25/fiver
Once the upload is complete, you’ll see the image in your Docker Hub account:
Go to your Azure account create a new “Web App for Containers”:
Enter details for and select the container:
Once provisioned, you could browse to your application, hosted on Azure, running within a Linux container:
Super cool and easy!
Discussion
Azure provides a highly scalable, configurable and easy to use Platform-as-a-Service (PaaS) environment for our ASP.NET Core web applications. Azure Web App is one of the simplest way to host web applications and the new Web App Container makes it really easy to host Docker containers.
Below I will give a high-level overview of Docker to get you started however, I suggest checking out these resources:
Docker
Docker provides a way to package up your application along with all its dependencies and then deploy as a unit.
First step to achieve this is to create an “Image”, which is a snapshot of everything our application needs to run. I like the analogy Wes Higbee uses, an image as a zip file or an installer that you require to install and run your application. Once you have the image (zip/installer) you could ‘run’ it and this running image in Docker terminology is known as a “Container”.
Images
There are two basic aspects of an image you should be aware of. Images are immutable i.e. once create, an image can’t be modified. You can of course create new images from an existing one and thus images are layered.
For instance, we need .NET Core Runtime to run our application and Microsoft has provided an image that contains all of that in an image called microsoft/aspnetcore. In our solution we took that image as a starting point, then copied our application on top and created a new image.
You could run the docker image ls
command to view a list of images on your local machine:
Containers
An image in a running state is known as Container. To run a container you could use the docker run
command:
docker run --rm -it -p 8080:80 fiver/basic
Here --rm
means to remove the container when it’s done, -it
means to show the interactive window and -p
maps the host (your machine) port to containers port:
Configuration Files
Docker has a command line interface (CLI) to manipulate images and containers however there are two configuration files that make things a lot simpler for us:
Dockerfile
This file contain instructions to build an image. We’ve used the following commands in our Dockerfile:
FROM
: specifies the base image required for our application.WORKDIR
: changes the working directory (inside the container) for other commands that follow.COPY
: copy files from host (source) to the container (destination).RUN
: executes a command inside the containerENTRYPOINT
: to configure a container that will run as executable. Here we specify the command to run along with any parameters.
In our solution we are creating our final image in two stages, first we create an image that contains the compiled and published application. For this step we use Microsoft’s image that contain ASP.NET Core build tools. Then we take the published files and create our final image, but this time only utilising Microsoft’s image that contain ASP.NET Core runtime.
The reason I am doing this is to have our final image as small as possible. Note the size of build vs. runtime aspnetcore images in the screenshot above!
Once we have our Dockerfile with instructions to build an image, we run docker build
command to create an image:
docker build -t fiver/basic .
Here -t
specifies the name for our image and .
specifies the context for paths specified inside the Dockerfile. In my solution the Dockerfile is in the same path as the application files.
docker-compose.yml
This file contains instructions (among other things) to run containers. Although you could run a container during docker run
command (as shown above), docker-compose.yml
file provides an easier solution when you have multiple containers to start.
In this file you declare the services (basically your containers) and the parameters they require to run. You could also specify the settings for building the image i.e. point the compose file to Dockerfile. The benefit of this is that you can build and run containers in one step.
Once we have our compose file, we run docker-compose up
command to execute it, as done in our solution. To stop the running services we can run docker-compose down
command.
Docker Hub
In order for us to distribute and deploy our images we need to store them in some form of registry. Docker Hub is one options, so is Azure Container Registry. In order to upload images to Docker Hub, you’ll need an account, which is free to setup. Then you could tag your image, login to Docker Hub and push images, like we did in our solution:
docker tag fiver/basic naushadt25/fiver
docker login -u [username] -p [password]
docker push naushadt25/fiver
Visual Studio 2017 Docker Support
In the above solution I created the files manually, which I would suggest you do to learn the basics, but VS 2017 provides very good support for Docker. Using Docker tools you could debug and deploy your ASP.NET Core applications from within Visual Studio. In my next post I’ll use these tools to create a solution with multiple projects and deploy to Azure.
Source Code
GitHub: https://github.com/TahirNaushad/Fiver.Asp.Docker.Basic