Docker MiniCrashCourse
Mini crash course for Docker and a simple C# application.
The whole guide and code can be found here to follow
Goal is to build a docker container and use docker-compose to utilize the docker container in the project.
Docker in 100 SecondsDocker Tutorial for BeginnersKubernetes Explained in 100 Seconds
- Install Docker on your machine
- Clone this repo and follow the guide
We are using the WeatherApi from Microsoft to demonstrate how to build a container that will expose its services on a port 8080.
This project is using C#, but we don’t need any tools on our machine to build this, since we are going to use the docker to do this for us.
docker-compose up -d docker-compose down docker-compose build
Test that the container is working
A Dockerfile is a recipe for how to build and/or run your application in a container.
For our building image we are to be using this image: mcr.microsoft.com/dotnet/sdk:latest
For our running image we are to be using this image: mcr.microsoft.com/dotnet/aspnet:latest
More information about these images can be found here: mcr.microsoft.com/dotnet/sdkmcr.microsoft.com/dotnet/aspnet
We are going to use a Dockerfile
and use use these aliases FROM <image>:<tag> as builder
and then use FROM <image>:<tag> as runner
to create a two step build and run. They can be named anything, this is just to illustrate.
Note: If your application is not compiled, and don’t need a build step, e.g. Python Flask webpage, React app, then it would suffice with a runner only image.
Build steps are done to reduce the size of the end image. E.g. if the application is written in Rust, keeping the build and the running image the same. The size of the container will be huge. Meaning, every time there is a change, you will have to download all this locally to get it down. Rust build image may, depending on your build, be 1Gb+ if not more.
With that said, lets build the container. In the root of the WeatherApi
project, where the Dockerfile
is placed we are to run these commands.
Example command
docker build . --tag weather-api:test
Result of this command should look something like this:
...snip...Successfully built 12042a3b5853
Successfully tagged weather-api:latest
Since it was reported successfully build we can use this container.
Lets just run it. When we do this, we wanna just give it a name for convenience and expose the ports it is supposed to use.
$ docker run -p 8080:80 --name weatherapi weather-api:latest info: Microsoft.Hosting.Lifetime[0] Now listening on: http://[::]:80 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: /app
Open your favourite browser and go to this URL http://localhost:8080/swagger/
Docker-compose is to orchestrate e.g. the launch of a project. Lets say that this API is relying on a backend database and this has to start before we can access the API.
We are just going to simulate that these two components are connected and talking together over code.
Let’s first create the docker-compose.yml for our api and try to launch this first.
The docker-compose.yml is living at the root, outside WeatherApi
folder. It can be placed otherplaces, but we need to be in the same folder as it is to run the docker-compose
command.
Check that you are in the same dir as the docker-compose.yml
and write the following.
$ docker-compose up
... snip
Creating docker-crashcourse_weather-api_1 ... done
Attaching to docker-crashcourse_weather-api_1
weather-api_1 | info: Microsoft.Hosting.Lifetime[0]
weather-api_1 | Now listening on: http://[::]:80
weather-api_1 | info: Microsoft.Hosting.Lifetime[0]
weather-api_1 | Application started. Press Ctrl+C to shut down. weather-api_1 | info: Microsoft.Hosting.Lifetime[0] weather-api_1 | Hosting environment: Development
weather-api_1 | info: Microsoft.Hosting.Lifetime[0] weather-api_1 | Content root path: /app
This command will if the image does not exist, build it and then launch it. Since we didn’t use the -d
switch, we are stuck in this terminal until we press `CTRL-C`` When we do this the service shuts down.
When using the -d
, it may look like this:
$ docker-compose up -d
Starting docker-crashcourse_weather-api_1 ... done
$ docker-compose down
Stopping docker-crashcourse_weather-api_1 ... done
Removing docker-crashcourse_weather-api_1 ... done
Removing network docker-crashcourse_default
Using docker-compose for a single container is very usefull. But since we are to add a database and claim that the WeatherApi
is depending on this database service.
So we are going to insert the following into the docker-compose.yml
.
Now, we are going to run the docker-compose
command again and see that the database is also starting.
$ docker-compose up ... lost of text weather-db_1 | Version: '10.4.12-MariaDB-1:10.4.12+maria~bionic' socket: '/var/run/mysqld/mysqld.sock' port: 3306
So this is all good and everything. But now the database and database startet at the same time and that is not good.
But we can add depends_on:
for the weather-api
service in the docker-compose.yml
file.
And when you then run docker-compose
you should see that the services are starting in order.
$ docker-compose up
... snip ..
weather-db_1 | 2021-02-17 19:02:26 0 [Note] mysqld: ready for connections. weather-db_1 | Version: '10.4.12-MariaDB-1:10.4.12+maria~bionic' socket: '/var/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution weather-api_1 | info: Microsoft.Hosting.Lifetime[0] weather-api_1 | Now listening on: http://[::]:80 ... snip...
Originally published at https://github.com.