4 Minuten zum Lesen

In diesem Artikel lernst du wichtige Details von Docker kennen, indem wir Docker bis an seine Grenzen ausreizen und Docker-in-Docker-Techniken verwenden.

Wenn du gerade erst mit Docker beginnst und es mit minimalem Aufwand ausprobieren möchtest, kannst du es direkt im Browser über die Webseite https://labs.play-with-docker.com/ ausprobieren. Du musst dich auf dieser Seite mit deinem Docker-Account anmelden.

Anschließend kannst du eine oder mehrere virtuelle Linux-Maschinen im Browser starten, in denen Docker direkt, ohne Installation, zur Verfügung steht.

Probiere es einfach aus! Alles, was du benötigst, ist ein Browser und einen kostenlosen Docker-Account, den du hier erstellen kannst. Selber verwende ich GitHub als Authentifizierungsprovider für meinen Docker-Account.

Probiere nun in einer Play-with-Docker-Instanz einfach Docker-Befehle aus, zum Beispiel

docker run hello-world

startet einen Docker-Container aus dem Docker Image hello-world.

In dem hello-world-Container werden noch interessante Tipps gegeben, wie du mit Docker weitermachen kannst. Wenn du Interesse an meinem Docker-Workshop hast, kannst du dich gerne hier zu einem unverbindlichen Kennenlerngespräch anmelden.

Play-with-Docker lokal starten

Dieser Kapitel ist nun für diejenigen, die schon Erfahrung mit Docker haben.

Wenn du Docker lokal auf deinem Rechner installiert hast, am einfachsten auf einem Linux-Rechner, kannst du Play-with-Docker auch lokal ausführen. Dafür musst du zuerst den Docker Swarm Mode einschalten. Auf Swarm Mode gehe ich hier nicht ein, da es ein komplexeres Thema ist. Der Befehl zum einschalten dieses Mode ist sehr einfach:

docker swarm init

und falls dein Rechner mehrere IP-Adressen hat, musst du mit dem Parameter --advertise-addr die gewünschte IP-Adresse für den Docker Swarm eintragen. Nimm hier einfach die IP-Adresse, über die dein Rechner von außen erreichbar ist. Starte nun Play-with-Docker lokal auf deinem Rechner mit dem Befehl

docker run -it \
    --name pwd \
    --rm \
    -p 3000:3000 \
    -v /var/run/docker.sock:/var/run/docker.sock \ 
       franela/play-with-docker:master

Aber Achtung: Der obige Befehl funktioniert wirklich nur unter Linux, da das Unix Socket /var/run/docker.sock auf deinem echten Linux-Rechner auf das entsprechende Unix Socket innerhalb des gestarteten Docker-Containers gebunden wird. Wenn du keinen Linux-Rechner hast, so kannst du Windows WSL installieren und dort eine Linux Distribution wie Kali Linux verwenden. Mein Arbeitsrechner ist auch ein Windows-Rechner mit WSL und einer Kali-Linux-Distribution.

Nach dem Start des obigen Docker-Befehls kannst du im Browser unter http://localhost:3000 Play-with-Docker verwenden und lokal eigene Instanzen starten, die wiederum Docker enthalten.

Du siehst nach dem Start einer PwD-Instanz, dass diese ein Docker-Container ist, das franela/dind als Image hat. dind steht hier für Docker in Docker, d.h., du hast einen Docker-Container, in dem du Docker verwenden kannst.

Ok, dann starten wir innerhalb der PwD-Instanz einen Docker-Container und schauen, wo dieser tatsächlich läuft. Führe

docker run -it ubuntu bash

innerhalb der PwD-Instanz

aus. Frage: Wo läuft der neu gestartete Container? Noch einmal zur Verdeutlichung: Ich habe eine Windows-Maschine mit WSL. Unter WSL läuft virtualisiert eine Linux-Distribution. Innerhalb dieser virtualisierten Linux-Umgebung habe ich einen Docker-Container mit Play-with-Linux gestartet. Dieser Container kann dann weitere Container starten mit franela/dind (Docker in Docker). Diese Container laufen ebenfalls innerhalb der Linux-Umgebung und werden als Instanzen in Play-with-Docker registriert. Der Ubuntu-Container, der in der PwD-Instanz gestartet wurde, läuft tatsächlich innerhalb dieser Instanz. Wir haben hier also tatsächlich einen Docker-Container, der innerhalb eines anderen Docker-Containers läuft.

Ehrlich gesagt, finde ich es extrem erstaunlich, dass dies so funktioniert und zeigt wie interessant die Docker Technologie eigentlich ist.

docker-cli in einem Docker Container

Das nächste Beispiel (ohne Play-with-Docker) nutzt die Möglichkeit, Unix-Sockets aus Linux auf sehr einfache Weise mit dem Parameter --volume oder -v in einen Docker-Container zu binden. Ein Unix-Socket ist, sehr einfach gesprochen, “nur” eine Datei, die dann über Docker Bind Mounts also dem Parameter -v in einen Docker-Container eingebunden wird. Insbesondere kann das von Docker verwendete Unix-Socket /var/run/docker.sock in einen Docker-Container eingebunden werden, sodass man den Docker-Host dann einfach aus einem Container steuern kann.

Als Basis-Image nehme ich das extrem leichtgewichtige alpine-Image und installiere darin das docker-cli, also den docker-Befehl oder die Client-Seite von Docker. Das Dockerfile sieht dann wie folgt aus:

# Use Alpine Linux as base image
FROM alpine:latest

# Update package lists and install basic packages
RUN apk update && apk upgrade && \
    apk add --no-cache \
    docker-cli

# Default command when container starts
CMD ["sh"]

Nun kann ich mit docker buildx build -t docker-cli . ein Docker-Image daraus bauen und mit

docker run -it \
    -v /var/run/docker.sock:/var/run/docker.sock \
    docker-cli

einen Docker-Container starten, in dem ich den docker-Befehl zur Verfügung habe und damit den Docker-Host steuern kann.

Wenn ich zum Beispiel docker container ps innerhalb des obigen Docker-Containers ausführe, dann sehe ich zum Beispiel alle Container, die auf dem Host laufen, inklusive des Containers, in dem ich mich momentan befinde.

Fazit

Ich hoffe, dass du nach diesem Artikel nicht allzu sehr von Docker-in-Docker verwirrt bist und du einige Dinge mitnehmen konntest, die dir vorher nicht klar waren. Die obigen Beispiele sind meiner Meinung nach sehr nützlich, um Docker besser und tiefer zu verstehen.

Tags:

Aktualisiert: