How to dockerize a .NET Core application
Install docker on your machine.
Test the installation$ docker run hello-world
The expected output is: Hello from Docker!
Read https://docs.docker.com/get-started/
The goal is to build an image that you can copy to the target machine and start to create a running container.
The container will contain all applications needed to run your app.
A container is launched by running an image. An image is an executable package that includes everything needed
to run an application — the code, a runtime, libraries, environment variables, and configuration files.
As an analogy: A docker-image is a class, a docker-container is an instance of a class.
First, you have to create a docker image on the development machine.
Docker images are created from docker-files (called Dockerfile without an extension) which contain statements that docker
will execute to create the image.
Go to the folder that contains the solution (.sln) file.
Create a file called ‘Dockerfile’ without extension.
Edit the Dockerfile in a text editor.
Here is my example Dockerfile:
FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build #FROM mono:6.0.0.313-slim AS build WORKDIR /app # debug output RUN pwd RUN hostname RUN uname -r # install npm RUN apt-get update && apt-get install -y curl RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - RUN apt-get update && apt-get install -y nodejs # copy csproj and restore as distinct layers COPY *.sln . COPY clone_angular/*.csproj ./clone_angular/ RUN dotnet restore # copy everything else and build app COPY clone_angular/. ./clone_angular/ WORKDIR /app/clone_angular RUN npm install RUN dotnet publish -c Release -o out FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime WORKDIR /app COPY --from=build /app/clone_angular/out ./ ENTRYPOINT ["dotnet", "clone_angular.dll"]
Execute docker to build the docker image from the Dockerfile.
Navigate to the folder that contains the docker file.$ docker build --tag=<TAG_NAME> .
‘docker build’ will run the Dockerfile.
During the execution, the operating system is 4.9.184-linuxkit.
So you are actually running a linux and apt-get is available for installing software.
On that linuxkit, there is no software installed.
If your build requires any tools, you have to install them on the linuxkit.
For example if your application uses angular, you will need node and npm you have to
install those tools first before building your app.
To install software, prepare a working installation command, then add a RUN command
to the dockerfile and paste the install command after it.
Once the dockerfile was executed, check if your docker installation lists your new image:$ docker image ls
You should see
REPOSITORY TAG IMAGE ID CREATED SIZE
<TAG_NAME> latest 8797820ed5c5 3 minutes ago 262MB
Start a container from that image:$ docker run -d -p 8888:80 <TAG_NAME>
In this command, the -d flag detaches the process from the command line. The container will run in the background and
the terminal is free for subsequent input. -p <EXPOSED_PORT>:<INTERNAL_PORT> will open the port 8888 in the host system
and bind it to the port 80 of the system running inside the container. This is necessary for accessing webapps from
the outside world. Open ports are shown in the last column of the output of the ‘docker container ls –all’ command.
The rightmost column shows which external port is bound to which internal port. In the example above you can now
access your webapp at localhost:8888. The last command is the image tag name to start the container from.
Errors during image creation
Q: The command ‘/bin/sh -c dotnet publish -c Release -o out’ returned a non-zero code: 1
A: You have to install software during the installation by adding commands to the Dockerfile
https://stackoverflow.com/questions/49088768/dockerfile-returns-npm-not-found-on-build
Deploy to the Remote server
The idea is to prepare an image in your local development environment.
Then create a .tar file of that image and upload the .tar file to the remote system.
https://stackoverflow.com/questions/23935141/how-to-copy-docker-images-from-one-host-to-another-without-using-a-repository
1. Install docker on the remote server:
The assumption is that your remote server is running Ubuntu Linux.
https://docs.docker.com/install/linux/docker-ce/ubuntu/
ssh root@<yourip> sudo apt-get remove docker docker-engine docker.io containerd runc sudo apt-get update sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io apt-cache madison docker-ce EXAMPLE: sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io sudo apt-get install docker-ce=18.06.3~ce~3-0~ubuntu docker-ce-cli=18.06.3~ce~3-0~ubuntu containerd.io sudo apt-get install docker-ce=5:19.03.1~3-0~ubuntu-xenial docker-ce-cli=5:19.03.1~3-0~ubuntu-xenial containerd.io sudo docker run hello-world
2. On your local machine, build a Dockerfile and an image from that Dockerfile. The steps for dockerizing an application are explained above.
3. On your local machine, create a .tar file from the docker image, upload and import it on the remote machine.
You can list all images available on your local machine:docker image ls
Then export one of the images to a file on your filesystem:
docker save -o <path for generated tar file> <image name>
docker save -o ./clone_tag_1_image.tar clone_tag_1
Now, zip the file to save time uploading it.
zip -r clone_tag_1_image.tar.gz clone_tag_1_image.tar
Upload the file to the server using scp:
scp <source> <destination>scp clone_tag_1_image.tar.gz root@<your_ip>:/temp
Unzip the image on the server:
gunzip clone_tag_1_image.tar.gz
Import the image on the server:
docker load -i <path to image tar file>
docker load -i /temp/clone_tag_1_image.tar
Run the docker detached while exposing the port 80 t0 8888:
docker run -d -p 8888:80 clone_tag_1
The web app should now be available via the servers IP on the port 8888. If it is not, check the firewall settings of your server.
Example repository
cd /Users/<USER>/dev/dot_net_core
git clone https://github.com/dotnet/dotnet-docker.git
Example
https://github.com/dotnet/dotnet-docker/tree/master/samples/aspnetapp$ docker run --name aspnetcore_sample --rm -it -p 8000:80 mcr.microsoft.com/dotnet/core/samples:aspnetapp
The app starts and is reachable on http://localhost:8000/
Cheatsheet
Version$ docker version
General info$ docker info
List all images downloaded to your local machine$ docker image ls
List all running docker containers$ docker container ls --all
Find all running docker containers and their IDs$ docker ps -a
$ docker port <ContainerID>
Stopping a container$ docker stop <ContainerID-Prefix>
Find info about a specific docker container$ docker inspect <containerid>
$ docker inspect <containerid> | grep IPAddress
Build an image from a Dockerfile$ docker build --tag=clone_tag_1 .
$ docker rm
$ docker container prune