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.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.2. Using the Docker tooling in Eclipse

To access the Docker functionality in Eclipse open the Docker Tooling perspective via the Perspective  Open Perspective  Other…​  Docker Tooling menu entry.

Appendix A: Docker resources