This tutorial contains some notes about using Docker as container for running virtual environments.
1. Introduction to Docker
1.1. What is Docker
Docker is a light weight container, allowing to run pre-configured system images on another operating system. Is is developed as an open source project, released under the Apache License, version 2.
You can package a applications, libraries or operating systems in a container, for example: * OS, * JVM, * App server * Application with its configuration
This makes the virtual machine portable across environments. Developers can use the same setup as you can use in your production environment.
Docker requires a very small amount of resources, as does not require an hypervisor for each container nor does it simulate a complete computer.
Docker addresses the following use cases:
-
You can to use a specific version of a operating system for testing
-
You want to run your software tests in an controlled environment
-
You want to configure a system and share the configuration
1.2. Docker components
Docker consists of the following components:
-
Images
-
Containers
-
Daemon
-
Clients
-
Registries
1.3. Dockerfile
A dockerfile allows to define images.
1.4. Images
Images are read-only templates which provide functionality for running an instance of this image. For example, the latest release of Ubuntu might be provided as image. Images are defined as layers, for example, you can add Java to the Ubuntu image and get another image based on this.
The Docker hub provides pre-configured images. You can modify existing images and save these modifications as new image.
1.5. Containers
Container are the started components based on images. They contain the actual application and dependencies but share the same kernel. They can be started, stopped, paused, deleted. Containers are immutable and disposable.
1.6. Docker Daemon
Is used to manage the container.
It runs natively on Linux and inside a VM on Windows and Mac OS X.
To start it use the docker
command.
1.7. Docker clients
Clients (CLI, IDE) run on host VM. They provide the tools to interact with container, i.e., to start them.
1.8. Docker registry
Images are saved in a registry and have an ID with consists of a repository and a tag. For example, fedora:22, is an image which contains the Fedora 22 OS from the fedora repository.
To use an image you have to pull it from a registry, to share an image with others you have to push it to one. The default Docker registry is the Docker Hub. You can upload your personal images to Github, in this case you add your user name as prefix to the image, e.g., vogella/fedore:22
1.9. Docker Compose
Compose is a tool for defining and running applications in multiple Docker container. You use a YAML file to configure your applications services.
1.10. Managing data in Docker
By default, Docker stores all data inside the container, which makes is harder to persist this data and to reuse the data in another container.
Docker offers two storage options for hosting data on the host machine:
-
volumes - stored on the host file system managed by Docker, preferred way of persisting data in Docker containers
-
bind mounts - old way of managing file includes, prefer using volumes
Docker volumes which are not explicitly created, are created the first time they are mounted to a container. If the container is stopped the volume still persists.
2. Docker installation and setup
Install Docker Toolbox from https://www.docker.com/. The installation is well described on the getting started page. For example https://docs.docker.com/linux/step_one/ describes the installation for Linux
Afterwards you can test you installation as described on the webpage:
sudo docker run hello-world
If you issue the command the first time, it downloads the hello-world image and start it.
To allow your user to run docker commands without the sudo prefix, configure a new group and add you user to it.
sudo usermod -aG docker ubuntu
Afterwards you need to logout and login again. Validate that you can run docker commands without sudo.
docker run hello-world
3. Docker commands
3.1. List all available images
docker images
3.2. List all available containers
Via the -a flag you list all contains.
Without -a
you only list the running containers.
docker ps -a
3.3. Create a new container
docker run image
3.4. Delete a container and an image
Use the following command to remove all your containers.
docker rm $(docker ps -a -q)
Use the following command to remove all your images.
docker rmi $(docker images -q)
3.5. Start a terminal session on a running container
Use this command to start a terminal session on a running container:
docker exec -it <container id> /bin/sh
If your image is using bash you have to replace /bin/sh with /bin/bash .
|
3.6. Start a terminal session on an image
Use this command to start a terminal session on an image:
docker run -i -t --entrypoint /bin/sh <image id>
3.7. Inspect a Docker container
docker inspect <image id>
4. Docker networking
4.1. Docker networking modes
Docker offers the following networking modes:
-
none
-
bridge (default)
-
host
-
container:<name|id>
-
user-defined network
4.1.1. None
docker run --net="none"
This option deactivates all external routes for the container. The only way to exchange data then is I/O or STDIN/STDOUT.
4.1.2. Bridge
docker run --net="bridge"
This is the default mode.
In this mode the host and the container can communicate via their ip addresses.
A veth (virtual ethernet interface) gets created on both host and container.
Both of those veths are put into a bridge which enables the communication.
The bridge is usually named docker0
.
4.1.3. Host
docker run --net="host"
In this mode the container shares the complete network stack of the host. This is useful for containers that need high performance network connectivity since the network traffic doesn’t have to go through virtualization.
Since this mode gives the container full access to all network interfaces and services of the host it poses a security risk. |
4.1.4. Container
docker run --network container:<name|id>
In this mode the container shares the network stack of another container.
4.1.5. User-defined network
docker network create -d bridge my-net docker run --network=my-net
You don’t have to use the default network bridge to connect your containers.
There are multiple network drivers to use.
This way you first create a network and then add the container you want to communicate with each other to it.
The simplest way is to use the bridge driver.
Docker container on a user-defined network can address each other via their host name since Docker provides an embedded DNS server.
Other possibilities are the overlay
and the macvlan
network driver.
5. Exercise: Allow a container in bridge mode to connect to a database on the host
In this exercise we are going to enable a docker container to connect to a Postgresql database on the host machine.
First we want to set the default bridge to an IP of our liking.
In /etc/default/docker
add the line:
DOCKER_OPTS="--bip=172.26.0.1/16"
This sets the ip address of the docker0 bridge to 172.26.0.1.
Then restart docker with
sudo /etc/init.d/docker restart
You can validate your change with
/sbin/ifconfig -a
Install postgresql, if you it already installed you can skip this step:
sudo apt-get install -y postgresql postgresql-contrib
Create a user and database:
sudo su - postgres
createuser --interactive -P my-user
Enter password for new role:
Enter it again:
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) y
Shall the new role be allowed to create more new roles? (y/n) n
createdb -O my-user testdb
By default postgres is only listening on localhost for incoming connections.
We want it to also listen on our docker0
bridge.
In /etc/postgresql/9.5/main/postgresql.conf
set
listen_addresses = 'localhost, 172.26.0.1'
Now we have to allow the user to connect through this addresss.
In /etc/postgresql/9.5/main/pg_hba.conf
set
# TYPE DATABASE USER ADDRESS METHOD
# with docker:
host testdb my-user 172.26.0.1/16 md5
To activate the changes restart postgres with
sudo /etc/init.d/postgresql restart
Assuming your CMD in your dockerfile is start.sh
you can add this to your starter shell script to expose the host ip to your application:
export DOCKER_HOST_IP=$(/sbin/ip route|awk '/default/ { print $3 }')
Now your docker container is ready to connect to the database on the host.
6. Exercise: Creating an Fedora based Unix system with Git
To run a bash on the latest Fedara system, use the following command.
docker run -t -i fedora /bin/bash
This creates a docker container (if not yet present), start the Fedora system and runs a shell in this container. You can now install Git into this container.
dnf install git
Afterwards you need to create a new container from the running container to persists the changes.
Use docker ps -l
to list the running container.
Create a new container with the docker commit
command.
This command supports the -m and -a flags.
The -m flag allows us to specify a commit message, much like you would with a commit on a version control system.
The -a flag allows us to specify an author for our update.
docker commit <yourcontainerid> vogella/fedoragit # alternatively include the author and use a commit message # docker commit -m "Adds Git to Fedora" -a "Lars Vogel" 9b14523f9e23 fedorawithgit
Then create and run the a new container based on your new image.
sudo docker run -t -i vogella/fedoragit /bin/bash
7. Exercise: Creating an Ubuntu based Unix system with Java
To run a bash on an Ubuntu 15.04 system, use the following command.
docker run -t -i ubuntu:15.04 /bin/bash
This creates a docker container (if not yet present), start the Ubuntu system and runs a shell in this container.
You can create your custom Docker images. For this you write a docker file describing your
image. This file is typically named Dockerfile
.
For example the following is a docker file which describes an image based on Ubuntu 15.10 with Java installed.
############################################################ # Dockerfile to run Java # Based on Ubuntu Image ############################################################ # Set the base image to use to Ubuntu FROM ubuntu:15.10 # Set the file maintainer (your name - the file's author) MAINTAINER Lars Vogel # Update the default application repository sources list RUN apt-get update # Install Java 8 RUN apt-get install -y openjdk-8-jdk
To create an Docker image from this file, enter the docker build -t [imagename]
command.
If you used for example ubuntujava8
as image name, you can now start the corresponding container with the
docker run -t -i ubuntujava8 /bin/bash
command and type in java
to check if the installation was successfully.
8. Docker support in the Eclipse IDE
The Eclipse Linux tooling project also provides Docker tooling for the Eclipse IDE, which allows to use the Eclipse IDE as Docker client. The tooling provides also an editor for Docker files.
8.1. Install Eclipse Docker tooling
Install the Eclipse Docker tooling from https://download.eclipse.org/linuxtools/updates-docker-nightly/
8.2. Using the Docker tooling in Eclipse
To access the Docker functionality in Eclipse open the Docker Tooling perspective via the
menu entry.Appendix A: Docker resources
A.1. vogella Java example code
If you need more assistance we offer Online Training and Onsite training as well as consulting