Docker

Siehe auch

Installation

RHEL 7+:

yum -y install yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum -y install docker-ce docker-ce-cli containerd.io

systemctl start docker

# Docker Compose
curl -L "https://github.com/docker/compose/releases/download/1.28.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version

Docker Cheat Sheet

docker run hello-world
docker run --interactive \
    --tty=false \
    --detach=false \
    --publish 80:80 \
    onlyoffice/documentserver
docker run --name=mongo \
    mongo:4.2
docker run --name=elasticsearch \
    --env="http.host=0.0.0.0" \
    --env="discovery.type=single-node" \
    --env="ES_JAVA_OPTS=-Xms512m -Xmx512m" \
    docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
docker run --name=graylog \
    --env=GRAYLOG_HTTP_EXTERNAL_URI="http://127.0.0.1:9000/" \
    --link=mongo --link=elasticsearch \
    --publish=9000:9000 --publish=12201:12201 --publish=1514:1514 \
     graylog/graylog:4.0
docker run --log-driver gelf –-log-opt gelf-address=udp://1.2.3.4:12201 mycontainer anyoptions

docker restart $CONTAINER

docker container ls --all
docker image ls --all
docker ps

# where are images located?
docker info

docker rm

# inspect a container, get IP address etc.
docker inspect
docker inspect --type container
docker inspect -f '{{.HostConfig.LogConfig.Type}}' 8e8323567545

# get the logs
docker logs -f ea87dde67282
docker logs -f container-name

# get a bash shell in the container
docker exec -it <container name> /bin/bash

docker stats --no-stream
docker stats --no-stream $(docker inspect -f {{.Name}} $(docker ps -q))

curl --unix-socket /var/run/docker.sock "http:/localhost/containers/<container id or name>/stats?stream=False"

docker --host=ssh://docker-host container stop $(docker --host=ssh://docker-host ps -a -q)
docker --host=ssh://docker-host container prune -f
docker --host=ssh://docker-host rmi $(docker --host=ssh://docker-host image ls -q)

Firewalling

Das Firewalling der Docker-Container ist kompliziert, da der Docker-Daemon selbst dynamisch Firewall-Regeln anlegt. Firewalling ist aber gerade bei Docker sehr wichtig, denn wenn bei --publish keine IP mitgegeben wird, hört der Port auf allen Interfaces des Hosts - inklusive Firewall-Regel, die einkommende Verbindungen erlaubt. Da dies den Usern meistens nicht bewusst ist, stellt das ein Sicherheitsrisiko dar.

FwBuilder / Firewall Builder und Docker vertragen sich leider nicht, da beim Neustarten der Firewall alle Regeln gelöscht werden - somit auch die des Docker-Daemons. Hier ist die einzige Option, dass die Erstellung der Regeln im Docker-Daemon deaktiviert und die Regeln manuell erstellt (siehe auch einen Blog-Post von firewalld) werden. Allerdings ist das nur möglich, wenn die Docker-Container IPs und Ports bekannt sind - somit nicht für den Einsatz auf einer Workstation geeignet.

Bei firewalld ist der Reload granularer implementiert, somit werden die Docker-Regeln nicht beeinflusst. Allerdings funktioniert hierbei eine Policy mit Ingress-Zone ANY und Egress-Zone docker nicht wie erwartet, da firewalld alle DNAT-Verbindungen schon vor den Regeln der Policy akzeptiert (ct status dnat accept in der firewalld filter_FORWARD). Das Problem wird in einem GitHub-Issue thematisiert aber nicht zufriedenstellend gelöst.

Daher müssen die Regeln in der DOCKER-USER Chain abgelegt werden. Das geht mithilfe den (deprecated) Direct-Regeln in firewalld:

firewall-cmd --permanent --direct --add-chain ipv4 filter DOCKER-USER
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -i lo -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j LOG --log-level info --log-prefix "DOCKER-USER DENY "
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 2 -j DROP

So werden nur Verbindungen von den Docker-Host aus erlaubt.

DNS

Docker interessiert in der Regel nicht, welche DNS lokal im System auf der Netzwerkkarte konfiguriert sind - es soll aber gezwungen werden, einen bestimmten DNS zu verwenden?

/etc/docker/daemon.json
{
    "dns": [
        "1.1.1.1",
        "1.0.0.1"
    ]
}
systemctl restart docker

Test:

docker run busybox nslookup www.linuxfabrik.ch

Timezones

Zeitzone setzen:

docker run --env TZ=Europe/Zurich debian:jessie date

Logging mit Docker

Docker und Logserver wie Graylog: Docker besitzt eine Feldbegrenzung bei „message“ von 16KB. Mehr ist nicht möglich - laut Docker müssen die Log-Plugins eine Art von „max log size“-Option anbieten, tut aber Stand heute (2018-06) kein einziger. Ein pures Weiterleiten per GELF und anderen macht also nicht glücklich. Statt dessen müssen die Container über filebeats direkt per Beats auf den Log-Server schreiben. Die Container, die das nicht können (sollen), schreiben per journald. journalctl wird dann per journal2gelf an den Log-Server weitergeleitet.

docker run --log-driver=gelf --log-opt gelf-address=tcp://192.168.209.9:12201
alpine echo 'Hello World'

Journald als Logging-Driver:

GELF als Logging-Driver:

/etc/docker/daemon.json
{
    "log-driver": "gelf",
    "log-opts": {
        "gelf-address": "udp://192.168.209.6:12201"
    }
}

docker-compose

cd path/to/docker-compose.yml
docker-compose up

# daemonize:
docker-compose up -d

docker-compose down

Troubleshooting

unable to configure the Docker daemon with file /etc/docker/daemon.json: the following directives are specified both as a flag and in the configuration file: log-driver

In einem systemd-File befindet sich sehr wahrscheinlich genau die gleiche Config-Einstellung wie in /etc/docker. Docker führt die Anweisungen nicht zusammen.

Error starting daemon: error initializing graphdriver: /var/lib/docker contains several valid graphdrivers: devicemapper, overlay2; Please cleanup or explicitly choose storage driver (-s )
rm -rf /var/lib/docker/devicemapper
systemctl start docker

Built on 2026-03-13