Docker

Docker is container virtualization environment]] which can establish development or runtime environments without modifying the environment of the base operating system. It has the ability to deploy instances of containers that provide a thin virtualization, using the host kernel, which makes it faster and lighter than full hardware virtualization.

Kernel
If the kernel has not been configured properly before merging the package, a list of missing kernel options will be printed by emerge. These kernel features must be enabled manually.

For the most up-to-date values, check the contents of the CONFIG_CHECK in file.

A graphical representation would look something like this:

After exiting the kernel configuration, rebuild the kernel. If the kernel rebuild also performs a kernel upgrade, be sure to rebuild the bootloader's menu configuration, then reboot the system to the newly recompiled kernel binary.

Compatibility check
There is a Docker way of checking the kernel configuration compatibility:

Emerge
Install and :

PaX kernel
Tools in the package are necessary for this operation. See Hardened/PaX Quickstart for an introduction.

For the hello-world example, set this flag for containerd-shim and runc:

If an issue with denied chmods in chroots occurs, a more recent version of Docker (>=1.12) is needed. Use the Keyword for Docker and its dependencies listed subsequently when running  again.

OpenRC
After Docker has been successfully installed, add it to the system's default runlevel then tell OpenRC to start the daemon:

If the registry service is required:

If additional options are required to be passed to the docker daemon, then edit the file. See upstream documentation for the various options that can be passed to the DOCKER_OPTS variable.

systemd
To have Docker start on boot, enable it:

To start it now:

To pass any additional options to the docker daemon, create the file. See the upstream documentation for various options that can be placed into this systemd specific configuration file.

Permissions
Add relevant users to the docker group:

Storage driver
By default, Docker will use the device-mapper storage driver. View Docker's settings in detail with the subcommand:

To change the storage driver, first verify the host machines kernel has support for the desired fileystem. The btrfs filesystem will be used in this example:

Be aware the root of the docker engine ( by default) must be adjusted to use the btrfs filesystem. If the btrfs storage pool is located under or, then be sure to change the root (call the 'graph' in docker speak) of the engine.

Networking
Network forwarding must be enabled for docker container networking to work.

This can be temporarily enabled using procfs:

A more permanent change can be made with:

OpenRC
OpenRC users will need to adjust the DOCKER_OPTS variable in the service configuration file located in. The example below displays a change to the storage driver and the docker engine root:

Start or restart the docker service in order to for the changes to take effect and then validate the changes:

systemd
systemd users will need to create a file in order to change the storage driver for the docker service. For example, to use the btrfs driver:

(Re)start the service in order to make the changes take effect:

Testing
In order to test the installation, run the following command:

That will first download from the Docker Hub the image named hello-world (if it has not been downloaded locally yet), then it will run it inside new namespaces. It purpose is just to display some text through a container.

Building from a Dockerfile
Create a new Dockerfile in an empty directory with the following content:

Run:

Own images
There are two different ideas how a container should be built:


 * The minimal approach: According to the container philosophy a container should only contain what is needed to serve one process. In this case ideally the container consists of one static binary.
 * The VM approach: A container can be treated like a full system virtualization environment. In this case the container includes a whole operating system.

Build environment for the image
The image can be created out of a live system or - preferably - out of a special build environment.

To create a build environment for the image, follow the Cross_build_environment guide. There is no need to emerge a full @system. The build essentials are enough.

The toolchain tuple could look like.

The build essentials can be build like this:

The minimal approach: Statically linked binaries using Crossdev
There are some caveats with this. The hints for statically linked binaries should be kept in mind for this.

To build an nginx-image, first chroot into the build environment (e.g. ).

Build the desired package statically linked:

Extract the binary package to a tmp dir (e.g. )

Change the nginx configuration. At least add  and swap   for.

Add, ,  and a appropriate  directory. Make sure the  has "files" instead of "compat" and the  file has an "nginx" user entry.

Create the docker image out of the current directory:

Spawn a container and start nginx:

Alternative minimal approach: Dynamically linked binaries using Kubler
Kubler is a Gentoo based image meta builder. It will help to automate the build process to create Gentoo based containers and is especially helpfulfor those new to Crossdev. It allows a fine graded configuration of the build process but also comes with a list of predefined containers that will be build on the current system according to current Portage, the script will extract the dynamic libraries required by the application and copy them in the container. The container are linked to a static busybox image that allow basic shell interaction but the only way to update it is rebuild it with the kubler script.

The VM-like approach
Create the image out of the full environment:

Spawn a new gentoo container and start a shell:

This image can used as a base image. To build a nginx image for example run emerge nginx inside the container and push it back as new image afterwards:

Docker service crashes/fails to start (OpenRC)
After adding  to DOCKER_OPTS and restarting the Docker service, Docker may crash. Check this with.

If this is the case, try adding the  USE flag for the Docker package, and updating Docker package.

Install Docker with the new USE flags

Docker service restart

Docker service fails to start (systemd)
Some users have issues on starting  because of device-mapper error. It can be solved by loading a different storage-driver. E.g. Loading “overlay” graph driver instead of “device-mapper” graph driver.

“overlay” graph driver requires "Overlay filesystem support" in kernel configuration:

Add following to, then re-emerge Docker will solve this issue:

In case of an error saying,, the docker0 network bridge may be missing. Please see the following Docker issue which provides a bash script solution to create the docker0 network bridge: https://github.com/docker/docker/issues/31546

Docker service runs but fails to start container (systemd)
If using systemd-232 or higher and receive an error related to cgroups:

Add the following line to the kernel boot parameters:

Docker service runs but fails to start container (systemd)
If using systemd-232 or higher, and it throws this error:

Add the following line to the kernel boot parameters:

If using systemd and received this error:

Run the following commands as root:

This is not ideal as these commands must be run after each reboot, but it works.

Docker service fails because cgroup device not mounted (systemd)
By default systemd uses hybrid cgroup hierarchy combining cgroup and cgroup2 devices. Docker still needs cgroup(v1) devices. Activate USE flag  for systemd.

Activate USE flag for systemd

Install systemd with the new USE flags

systemd-networkd
If  is used for network management, additional options are needed for IP forwarding and/or IP masquerade.

These options are used instead of the sysctl settings for ip forwarding and/or masquerade.

In case the Docker containers are shutting down, with errors from  that complain of not being able to assign persistent MAC address to virtual interface(s): See https://github.com/systemd/systemd/issues/3374#issuecomment-339258483

External resources

 * Official Docker installation documentation
 * Docker introduction for beginners
 * nftables firewall for docker