Deploy ASP NET Core application on Docker Linux container
Deploy ASP NET Core application on Docker Linux container from Windows
Few weeks ago we saw how we could run ASP NET Core application on Ubuntu. This proving that a .NET Core Application can run on a Linux system, today we will be taking it a step further and see how we can deploy our application in a Docker Linux container. This post will be composed by three parts:
- Install Docker on Windows
- Docker basic commands
- Create ASP NET Core application
1. Install Docker on Windows
The first step is to go to the official site, sign up and download Docker CE.
Once downloaded, install Docker.
After being installed you should be able to right click on the icon > Settings on the Docker notification icon and see that Docker is running by checking the status at the bottom left, it should say Docker is running
.
Open PowerShell
and type docker run hello-world
.
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
d1725b59e92d: Pull complete
Digest: sha256:0add3ace90ecb4adbf7777e9aacf18357296e799f81cabc9fde470971e499788
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
You just downloaded the hello-world
image and ran it in a container which printed Hello from Docker
which was redirected to the console.
Useful link to the Docker orientation https://docs.docker.com/get-started/#prepare-your-docker-environment
Fix Docker not starting:
- Check that Hypervisor is enabled by opening the
Windows Features
and check if every checkbox is selected underHyper-V
.
- Next Under Hyper-V Manager check that
MobyLinuxVM
is inRunning
state.
- If it isn’t running, Docker fails to start, virtualization might not be enable on your computer and you will have to enable it on BIOS.
2. Docker basic commands
Now that Docker is installed and we can start build images and running containers, we can look into some of the terminology and commands from the CLI.
An image is a set of layers describe by the Dockerfile
. It represents a state of an environment. It is built with docker build
. There can be multiple version of the image tagged to different versions. A container is a running instance of an image bootup using docker run
. Multiple containers can be started from the same image.
To manage image and containers, we can use the commnad docker image ...
and docker container ...
.
For example to list all the containers running:
docker container ls
Or to see all images:
docker image ls
A container can be seen as a running process, it can be stopped using the following command:
docker container stop [container-id]
Or killed:
docker container kill [container-id]
Rogue images and containers can be cleared with prune
:
docker image/container prune
Images and containers can be removed using rm
with
docker image/container rm [image or container id]
Standard output are redirected and can be viewed using:
docker container logs [container-id]
Lastly if we want to inspect the content of the container, we can get access to a bash interactive shell by executing the following:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a7ab376d75ab dockertest:dev "dotnet DockerWebApp…" 32 seconds ago Up 30 seconds 0.0.0.0:5000->80/tcp cocky_montalcini
$ docker container exec -it a7ab376d75ab bash
root@a7ab376d75ab:/app#
exec
is used to execute a command on a running container, here we open an interactive shell with -it
and execute bash
. To exit, type exit
.
root@a7ab376d75ab:/# exit
exit
kimserey.lam@KLAM C:\Projects
Now that we have Docker installed, and know some functionalities of the docker CLI
, let’s see how we can setup an ASP NET Core application running in Docker Linux container.
3. Create ASP NET Core application
In order to get an ASP NET Core application running on Docker, we need to create a Dockerfile
which is a file containing instruction on how to build a Docker image of our application.
3.1 Dockerfile
Start by creating an empty ASP NET Core application. Then right click on the project and select Add Docker support
.
Once added, the toolbox will have created the following Dockerfile in your project:
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY DockerWebApp/DockerWebApp.csproj DockerWebApp/
RUN dotnet restore DockerWebApp/DockerWebApp.csproj
COPY . .
WORKDIR /src/DockerWebApp
RUN dotnet build DockerWebApp.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish DockerWebApp.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "DockerWebApp.dll"]
The Dockerfile contains multiple step, FROM
specifies the image from you will start, WORKDIR
specifies the current dictory within the container. COPY
is used to copy files and RUN
is used to run processes. At the end of the script we defines the ENTRYPOINT
as being the dotnet process with the dll as argument just like we would run dotnet DockerWebApp.dll
in our command prompt.
One we have the Dockerfile, we can build by running the following in the root of the application:
docker build -f DockerWebApp\Dockerfile -t dockertest:dev .\
docker build
builds the image, -f
specifies the dockerfile paht while -t
represents the name of the repository and the tag of the application. We can see the image built with docker image ls
.
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
dockertest dev 6663b809a99a 4 seconds ago 255MB
microsoft/dotnet 2.1-aspnetcore-runtime 40d759655ea3 7 days ago 255MB
microsoft/dotnet 2.1-runtime cc240a7fd027 7 days ago 180MB
microsoft/dotnet 2.1-sdk e1a56dca783e 7 days ago 1.73GB
docker4w/nsenter-dockerd latest cae870735e91 11 months ago 187kB
Once built we can run this image by mapping the port of the container to 5000 on the local machine.
docker run -p 5000:80 dockertest:dev
If we look at the list of containers, we will see our container runnning and the PORTS
specifies that the local machine redirects traffic from 5000 to 80 in the container.
docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a7ab376d75ab dockertest:dev "dotnet DockerWebApp…" 32 seconds ago Up 30 seconds 0.0.0.0:5000->80/tcp cocky_montalcini
Navigate to http://localhost:5000
and you will be able to hit your application running in Docker container.
$ docker container logs -f a7ab376d75ab
Hosting environment: Production
Content root path: /app
Now listening on: http://[::]:80
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/
Now we can build images and run ASP NET Core application containers but we lost are ability to use the Visual Studio debugger because it’s no longer a process that can be easily attached with a debugger.
To fix that Visual Studio and Docker tools provide an extension which gives full integration of the debugger via docker-compose
and dcproj
.
When we enabled Docker support, a dcproj
was created and saved under the solution. The project contains a docker-compose.yml
and an override which are used to orchestrate deployment.
version: '3.4'
services:
dockerwebapp:
image: myregistry/dockerwebapp
build:
context: .
dockerfile: DockerWebApp/Dockerfile
Here we only have one service dockerwebapp
and under the override file:
version: '3.4'
services:
dockerwebapp:
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "5000:80"
We map the local port 5000 to the container 80 which serves our ASP NET Core application.
Everytime we make changes to this file, we can see the Docker
Output on Visual studio:
version: '3.4'
docker ps --filter "status=running" --filter "name=dockercompose5923735658168190169_dockerwebapp_" --format {{.ID}} -n 1
docker-compose -f "C:\Projects\DockerWebApp\docker-compose.yml" -f "C:\Projects\DockerWebApp\docker-compose.override.yml" -f "C:\Projects\DockerWebApp\obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose5923735658168190169 --no-ansi build
Building dockerwebapp
Step 1/3 : FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
---> 40d759655ea3
Step 2/3 : WORKDIR /app
---> Using cache
---> 058625e3a437
Step 3/3 : EXPOSE 80
---> Using cache
---> e220acc00b8b
Successfully built e220acc00b8b
Successfully tagged myregistry/dockerwebapp:dev
docker-compose -f "C:\Projects\DockerWebApp\docker-compose.yml" -f "C:\Projects\DockerWebApp\docker-compose.override.yml" -f "C:\Projects\DockerWebApp\obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose5923735658168190169 --no-ansi up -d --no-build --force-recreate --remove-orphans
Recreating dockercompose5923735658168190169_dockerwebapp_1 ...
Recreating dockercompose5923735658168190169_dockerwebapp_1 ... done
Done! Docker containers are ready.
This means that everytme we change the file, the image is updated. For development, the container is already running so there’s no need to manually run it. All we have to do is to select the docker project from Visual Studio and set it as a startup project, run it, we will now be able to breakpoint in the project.
And that concludes today post! We now have an ASP NET Core application deployed on Docker Linux container which can be debugged locally via breakpoint.
Conclusion
Today we saw how we could install Docker Linux containers on Windows, we discovered some of the most common features of the Docker CLI to manage images and containers and lastly we saw a concrete example of how to setup an ASP NET Core application running in Docker Linux container and how we could breakpoint to debug code while running in the container. Hope you like this post, see you next time!
Comments
Post a Comment