docker

Janne Alatalo
janne.alatalo@jamk.fi

Image vs. Container

  • You use docker container run to create a container from some image
  • You can have any number of containers that are started using the same image
  • The image contains a starting point for all containers
    • Meaning that if some file exists in the image, then it's available in all containers that are started from that image
    • Removing the file inside one container doesn't remove it from all of the containers
  • Analogies:
    • Class vs. Object from object oriented programming
    • Executable vs. Process
      • Somewhere in your computer's file system there is the executable binary for notepad
      • You can have multiple notepads running at the same time, but they are executing the same binary
    • Blueprint vs. House
Starting a container: docker container run

					# Starts a container with nginx-container name
					# from the nginx dockerhub image
					docker container run --name nginx-container -p 80:80 -d nginx
					

--name nginx-container the container name

-p 80:80 forwards the local port 80 to container port 80

-d runs the container in the background

nginx the last parameter is the image name

Container port forward
  • Forwards a port from the host computer to the container
  • -p or --publish argument for the docker container run command
  • Valid formats
    • hostPort:containerPort
    • ip:hostPort:containerPort
    • containerPort
    • ip::containerPort

					# Bind to host port 8080 and forward it to container port 80
					docker container run --name nginx-8080 -p 8080:80 -d nginx
					# Bind to host port 127.0.0.1:8888 and forward it to
					# container port 80
					# (only traffic with dest ip 127.0.0.1 is forwarded)
					docker container run \
					  --name nginx-localhost -p 127.0.0.1:8888:80 -d nginx
					
List containers: docker container ls
  • List all running containers

							docker container ls
						
  • List all containers

							docker container ls -a
						
  • Example output

					CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                    NAMES
					249cf4240596        nginx               "nginx -g 'daemon of…"   18 seconds ago       Up 16 seconds       127.0.0.1:8888->80/tcp   nginx-localhost
					f549ece8fc1e        nginx               "nginx -g 'daemon of…"   About a minute ago   Up About a minute   0.0.0.0:8080->80/tcp     nginx-8080
					f18843473186        nginx               "nginx -g 'daemon of…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp       nginx-container
					
Container environment variables
  • Very often the containers are configured using environment variables
  • Container environment variables are given at the container startup

					docker container run \
						-d \
						--name postgres \
						-e POSTGRES_USER=user1 \
						-e POSTGRES_PASSWORD=supersecret \
						postgres
					

Image management

List the images: docker image ls


					docker image ls
					

Download an image: docker image pull


					docker image pull nginx
					

Remove an image: docker image rm


					docker image rm nginx
					

Older short docker commands

  • The new commands are easy to remember but longer
New commandShort command
docker container {run, start, stop, exec, logs, cp}docker {run, start, stop, exec, logs, cp}
docker container lsdocker ps
docker image {pull, push, build, tag}docker {pull, push, build, tag}
docker image lsdocker images
docker image rmdocker rmi
Mounting a directory to the container (bind mount)

					mkdir /tmp/www
					docker container run \
						--name nginx-container \
						-p 80:80 \
						-v /tmp/www:/usr/share/nginx/html:ro \
						-d \
						nginx
					

-v /tmp/www:/usr/share/nginx/html:ro

source directory (host):destination directory (container)[:optional param]


					echo '<html><body><h1>Hello world!</h1></body></html>' > /tmp/www/index.html
					

Docker volumes
Docker volumes example

					# Create a volume named psql-vol
					docker volume create psql-vol

					# Same syntax as the bind mount
					docker container run \
						--name postgresql-container \
						-p 127.0.0.1:5432:5432 \
						-v psql-vol:/var/lib/postgresql/data:rw \
						-d \
						postgres
					

					# List the volumes
					docker volume ls

					# Show the volume information
					docker volume inspect psql-vol

					docker container stop postgresql-container
					docker container rm postgresql-container
					docker volume rm psql-vol
					
Debug commands: docker exec
  • Executes a command inside the container
  • Requires that the container is running

					docker exec -it postgresql-kontti bash
					

-it is required for interactive commands


					docker exec postgresql-kontti cat /etc/passwd
					
Debug commands: docker cp
  • Copies files and folders between the host and a container
  • Requires that the container is running

					# Copy file from the container to the host
					docker container cp nginx-kontti:/etc/nginx/nginx.conf /tmp/nginx.conf

					# Copy file from host to the container
					docker container cp /tmp/nginx.conf nginx-kontti:/etc/nginx/nginx.conf
					
Debug commands: docker logs
  • Show all container logs
  • Includes everything that the process has written to stdout and stderr

					# Print all of the postgresql-container container logs
					docker container logs postgresql-container

					# Real time follow mode
					docker container logs -f postgresql-container
					
Docker networking
Docker networking: ping demo
  • Docker starts a DNS server to user created networks
    • Container name can be used in the place of IP address

					# Create a new network
					docker network create my-network

					# Start two containers
					docker container run -d -t --rm --name container1 --net my-network busybox
					docker container run -it --rm --net my-network busybox

					# Inside the container
					ping container1
					
Assignment: PHP web server
  • Create a php server container:
    • Use php:7.1-apache docker image from Dockerhub
    • Serve files from the host computer's /tmp/php directory
    • Bind to default http port (port 80) on the host computer
  • Important info about php:7.1-apache image
    • Inside the container the apache process is serving /var/www/html directory
    • Inside the container the apache process binds to port 80
  • Tips:
    • docker run or docker container run creates a new container
    • You need to use the -p argument to forward a port from host to container
    • You need to use bind mount to mount host directory inside the container
Assignment: Wordpress with docker
  • Use the readymade Wordpress image from Dockerhub
  • Wordpress requires a database, use this Mysql image from Dockerhub
    • Note! Use image tag mysql:5.7 (Wordpress requires this version)
  • Create the containers so that:
    • They are in the same docker network
    • Host computer port 80 is forwarded to Wordpress
    • Use bind- or volume mount to save the /var/lib/mysql directory outside of the mysql container
  • Wordpress container is configured with the following environment variables:
    • WORDPRESS_DB_HOST
    • WORDPRESS_DB_USER
    • WORDPRESS_DB_PASSWORD
    • WORDPRESS_DB_NAME
  • Mysql container is configured with the following environment variables
    • MYSQL_ROOT_PASSWORD
    • MYSQL_DATABASE
    • MYSQL_USER
    • MYSQL_PASSWORD
Dockerfile
  • Includes all the commands for creating a docker image
  • Executes the commands on top of the base image

						# Docker base image
						FROM debian:buster-slim

						# Commands that are executed during image creation
						RUN apt-get update \
							&& apt-get install -y nginx
						RUN echo "hello world" > /var/www/html/index.html

						EXPOSE 80
						VOLUME /var/www/html

						# Command that is executed when the container is started
						CMD ["nginx", "-g", "daemon off;"]
					

Dockerfile instructions

  • FROM Defines the base image
  • RUN Executes a command during the building phase
  • COPY and ADD Copies files inside image
  • ENTRYPOINT ja CMD Defines the command that is executed at container startup
  • EXPOSE Information about the ports that the services are using
  • VOLUME Defines a mount point
  • USER Defines the user that is used to execute the following RUN, ENTRYPOINT and CMD instructions

Building the image: docker image build


					mkdir /tmp/dockerfile-example
					cd /tmp/dockerfile-example
					curl http://alaja.pages.labranet.jamk.fi/docker-koulutus/files/example-dockerfile > Dockerfile

					docker build -t my-nginx-image .

					# Images can be tagged with version too
					docker build -t my-nginx-image:v0.1 .

					docker run --name my-nginx-container -d my-nginx-image:v0.1
					

Exercise

  • Implement a Dockerfile for the Real World demo application (Conduit)
  • Dockerizing a Node.js web app is a great guide to get you started
  • Test the images that you created from the Dockerfiles by installing them on your virtual machine
  • Extra tasks
    • Add a non root user to the images that runs the main process
    • Optimize the backend image size by using small base image
    • Use the multi-stage build strategy to create the image for the frontend project
      • npm run-script build builds an optimized build for the project
      • The contents of the build directory can then be served with any normal http server
      • Create a Dockerfile that first builds the project with the nodejs image and then serves the build folder with some http server image
      • Note that you must set the REACT_APP_API_ROOT during build time with ARG and --build-arg argument

Docker registry authentication

Pushing an image to registry: docker push

Example: GCE Container Registry

					# Ubuntu instructions below.
					# For generic linux instructions follow this guide:
					# https://cloud.google.com/sdk/docs/quickstart#linux
					sudo apt-get install apt-transport-https ca-certificates gnupg
					echo "deb https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
					curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
					sudo apt-get update && sudo apt-get install google-cloud-sdk

					# Initialize the tool
					gcloud init

					# Authenticate docker daemon to registry
					gcloud auth configure-docker
					

					docker image tag my-nginx-image:v0.1 eu.gcr.io/yourprojectid/my-nginx-image:v0.1
					docker image push eu.gcr.io/yourprojectid/my-nginx-image:v0.1
					

Docker compose

  • Configuration tool for multi container applications
    • For example. Usually web-applications are using at least two containers (database, backend)
  • Installation
  • Wordpress demo

Exercise

  • Continue doing the exercise from yesterday if not done yet
  • Create a docker compose file for the real world app
    • The compose file must start all three containers
    • docker-compose build should build the images
    • docker-compose up should start the containers
    • Add a volume to mongo container that saves the database state
  • Extra tasks:
    • Claim your credits to Google Cloud (link posted to Teams)
    • Push the docker images to Google Container Registry (GCR)
    • Create a new docker compose file that uses the images from GCR
    • Think how docker compose could be used to setup a development environment
    • Try using environment variables to configure for example REACT_APP_API_ROOT