Docker

Intro

Containers work by isolating the differences between applications inside the container so that everything outside the container can be standardized. At the core of container technology are cGroups and namespaces. Control groups work by allowing the host to share and limit the resources each process or container can consume. Processes are limited to see only the process ID in the same namespace.

A Docker environment is made up of filesystems layered over each other. At the base is a boot filesystem, docker’s next layer is the root filesystem, rootfs. Then Docker takes advantage of a union mount to add more readonly filesystems on top. These filesystems are called "images". Finally, Docker mounts a read-write filesystem on top of any layers below. This is where whatever process we want our Docker container to run will execute.

User images are named using "initial/name:tag"

The RUN instruction in a Dockerfile executes commands on the current image and commits the results.

Useful command

docker build -t initial/name .
docker commit containerid imagename
docker ps
docker images
docker run -i -t initial/name /bin/bash
docker run -it --rm -p 8888:8080 tomcat:8.0 (1)
docker run -d --net compose_default puppet/puppet-agent-centos (2) (3)
docker history busybox:1.24 (4)
docker exec -it containerid bash
docker info
docker inspect
docker stack deploy [OPTIONS] -c compose_file.yml
docker swarm join --token XXYYZZWWWWW
1 map tomcat 8080 port to the host on port 8888
2 -d for detached (will run in the background)
3 --net compose_default specify the network (this one is created by default by docker-compose)
4 show image layers

Network

When a container launches, the docker engine assigns it a network interface with an IP address, a default gateway, and other components, such as a routing table and DNS services.

We connect a docker container to a particular network by using the --net option when launching it.

Docker offers the following network types.

  • host

    The container shares the same IP address and network namespace as that of the host.

  • bridge (default)

    The container runs in a private network internal to the host. Communication with other containers on the same host is enabled through the docker0 bridge.

    Communication with services outside of the host goes through NAT before exiting the host. Ports mapping needs to be explicitly described with the -p option. The docker daemon creates iptables rules (Netfilter on linux) to publish these ports.

  • custom bridge

    Same as above but with a dedicated bridge. This allows to isolate containers running on the same host.

  • container-defined

    Similar to how a Pod works in Kubernetes. Services running on one container can talk to services running on the other via the localhost address.

    docker run -it --name=container-a busybox /bin/sh
    docker run -it --name=container-b --network=container:container-a busybox /bin/sh

It is possible to extend the number of provided types using network driver plugin.

Cross-host networking usually uses an overlay network that is setup by Swarm.

Standard

OCI

Open Container Image

runC

Lightweight universal run time container, which abides by the OCI specification

containerd

container runtime which can manage a complete container lifecycle (spins up runC)

docker engine

communicates with containerd

Links is used to enable secure communication between two containers. The first container (also called child [1]) will expose a port and be labelled with a name.

# Source or first container
sudo docker run -it -name puppetmaster pra/pmaster /bin/bash

# Recipient (also called parent have all info to connect to the first
sudo docker run -it -name minion -link puppetmaster pra/minion /bin/bash

SSH-tunnel

ssh -q -M -S my-ctrl-socket -fnNT -L 27017:localhost:27017 alhazen@pulp.irisnet.be

# to use the host network: --net host
docker run --net host -e PULP_LOGIN=$(PULP_LOGIN) -e PULP_PWD=$(PULP_PWD) --rm -v $(PWD):/code -ti test /code/bin/clean.py $(ENV) --repo-name=$(REPO_ID)

ssh -q -S my-ctrl-socket -O exit alhazen@pulp.irisnet.be 2> /dev/null

Export/Import

Export acts on containers ! It currently does not work from containers to images …​ It is really briddle right now (just wait for 1.0)

In the meanwhile it is possible to use any image as your base image in the Dockfile …​

Mount

The VOLUME instruction from the Dockerfile is used to indicate to the destination volume inside the container. It is only there for documentation sake.

Volumes are initialized when a container is created. To do so, you will pass the option -v to docker run:

docker run -it -v /path/host:/path/container:ro nginx:latest /bin/bash

Docker compose

docker-compose.yml
version: '3'

volumes:
  esdata1:
    driver: local
  esdata2:
    driver: local

networks:
  esnet:

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:<%= @version %>
    container_name: elasticsearch
    environment:
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - esdata1:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"
    networks:
      - esnet

Some common commands:

docker-compose up
docker-compose ps
docker-compose logs -f
docker-compose stop
docker-compose rm

Swarm

Manager are just worker with extra permissions to control the swarm cluster.
Network

Swarm provides an inbuilt facility of services (in the Kubernetes sense) & Load Balancing. When a swarm cluster is initialized it creates an overlay network to allow containers in the cluster to communicate with each other.

POC (2017)

Initial Win7 host setup

Win7 hosts a docker ubuntu VM (standard install) using vagrant.

Change the Vagrantfile to mount the shared `puppet-stack-middleware`directory:

config.vm.share_folder "puppet-stack-middleware", "/media/puppet-stack-middleware", "C:/Users/pradermecker/VirtualBox VMs/shared/puppet-stack-middleware"

Connection to the docker vms from an arch vms with:

ssh -p 2222 vagrant@10.0.2.2

Create a dir puppetmaster and a file inside called Dockerfile. Build with sudo docker build .

Then you need to ssh-copy-id your public id_rsa.pub key to be able to fetch the Docker configuration from Github.

Trouble Shouting

WARNING

In centos 6.4 usePAM needs to be set to no while it needs to be set to yes in 6.5

WARNING

The Centos latest official images, currently 6.5, comes with a broken centos.plus version of libselinux. To remove it you need to:

yum downgrade --skip-broken libselinux libselinux-utils

Swarm node

Each node is configured by puppet and contain:

  • a container swarm running inside a docker (spawn with the docker engine daemon)

  • a docker registrator running inside a docker (spawn with the docker engine daemon)

  • a consult agent (doesn’t run within a docker)

DNS

You can use Consul as a DNS service. dnsmask is configured within each swarm node while every dockers inside a node is running with --dns 172.17.0.1.[2]


1. This is odd because the source is usually a server and it has to be started first …​
2. the DNS host for every docker is always 172.17.0.1