jump to content
Snippets and tips
  1. Home
  2. Holiday
  3. Posts
  4. Tools
  5. Tags
  6. Categories

Docker

The most convenient low-level virtualization

Experiences and tricks to remember from my past

Virtualization starts at the lowest level with a chroot-environment, then continues via docker, docker swarm, kybernetes, para-virtualized VM to full hardware virtualized machines. It further advances to Virtual Network Functions that include virtual hardware, setup of software and operation and maintenance.

Docker containers are virtualized both on the root file system, the process control groups (cgroups), and network namespaces.

Advantages are:

  • containers are slim and only contain a few binaries
  • filesystem is provided by the host system (no fixed disk size)
  • CPU operations have almost 0 penalties from virtualization
  • Restart from fixed configuration/setup
  • NAS for selected ports, protection of the remaining system
  • Network is configured on entry - no dhcp or similar

Disadvantages are:

  • init-1-process is not available, hence no systemd or init process can run
  • network is routed - a slight penalty
  • network is not configurable
  • filesystem is a union stack - not peak performance

Recommendation #

Use docker compose, it makes administration so much easier. One can administrate several containers at once. Use dedicated build directories for building images.

Clean images from time to time. Docker is happy to use local disk space for all downloaded images.

If possible, use multi-stage Dockerfiles. The first stages can build a functioning environment, while the last one only contains the necessary binaries for operation.

Networking #

Usually, docker automatically creates networks and attaches them to the host network via a bridge. Each specified network is created separately and independently from the others. A name resolver like DNS is provided that resolves hostnames to IP-adresses.

For testing a bigger system comprising several components, one can implement a system in docker compose and test the integration.

Network visible docker containers #

One can place the network interfaces of a container on the local network using IpVLan. The following commands create such a network which can be used in docker-compose.yml files as external networks.

1
2
3
4
5
6
7
docker network create \
    -d ipvlan \
    -o ipvlan_mode=l2 \
    --subnet=192.168.0.0/22 \
    --gateway=192.168.0.1 \
    -o parent=enp0s31f6 \
    backbone

There is one major caveat. The docker host computer is not able to ping the container ports due to some multi-using of the parent interface.

Output from building #

The newer docker builder shows the progress in a ninja-manner by just showing a few last lines and an overview. The old verbose behavior can be enabled by using the command line argument to docker build --progress=plain. Docker-compose does not offer the option to equip some builds with this verbose option. Here, one needs to instruct the builder by an environment variable, which has to be set before invoking docker compose either there or in .profile. The line is:

1
export BUILDKIT_PROGRESS=plain

Caching packages for package managers #

Developing the right dockerfile with the right configuration leads to frequent builds. That includes installing packages onto the base image. The frequent download of packages is both a burden onto the network and also delays the build. Fortunately, it is possible to cache the downloaded packages. Where they are stored, depends on the package manager.

For Ubunto the following does the trick:

Docker part:

1
2
3
4
5
6
7
RUN --mount=type=cache,target=/var/cache/apt \
  --mount=type=cache,target=/var/lib/apt \
  date \
   && apt update \
   && apt install -y  nginx php-fpm php-mysql php-xdebug \
   && apt install -y less strace mlocate net-tools \
   && date 

For apt, we need to remove /etc/apt/apt.conf.d/docker-clean (or simply overwrite it with an empty file) and add the following to /etc/apt/apt.conf.d/keep-packages:

1
Binary::apt::APT::Keep-Downloaded-Packages "true";

Running xnetload will show if it works. Spikes should only occur when it is reasonable.