Erster Schritte mit Docker

Dass Docker und das damit verbundenen Konzept der Container mehr als nur ein Hype sind, wird deutlich, wenn man sich aktuelle Trend-Entwicklungen im IT-Bereich anschaut. Unabhängig von Docker sprach sich auch Kernel-Entwickler Matthew Garrett für die Nutzung von Container als Teil eines Sicherheitskonzept aus, obwohl er auch zugleich mahnt, dass noch viel Arbeit in Tools und die Sicherheit im Kernel gesteckt werden müsse.

Für mich ist das Grund genug mir mal den aktuellen Stand von Docker und seinen Geschwistern, wie Docker Compose anzuschauen. Ziel soll es in dieser Artikelserie sein, einen LAMP-Stack auf Basis von Docker, aufzubauen. Im ersten Teil machen wir den Anfang mit der Installation von Docker auf einer Maschine mit Debian Jessie in der Minimal-Installation.

Doch zunächst möchte ich auf die wirklich ausführliche Dokumentation der offiziellen Docker Website hinweisen, die einen sehr guten Einstieg in die Thematik darstellt.

Docker Engine

Wir machen den Anfang mit der Installation der Docker Engine, der Basis, um mit Docker überhaupt loslegen zu können. Als Voraussetzung muss ein 64-bit-System mit mit einer Mindest-Kernel-Version von 3.10 herhalten. Wer den Standard-Kernel von Debian Jessie nutzt, wird hier keine Probleme bekommen, wie man der Ausgabe von uname -r entnehmen kann. Dass wir Root-Rechte brauchen, setze ich in dieser Anleitung ebenfalls voraus.

Wir beginnen, wie üblich, mit der Aktualisierung der Pakete und Paketquellen. Anschließend installieren wir das für die Docker-Quellen notwendige Paket apt-transport-https.

apt-get update && apt-get upgrade
apt-get install apt-transport-https

Es folgen die auch in der offiziellen Dokumentation beschriebenen Installations-Schritte, die ich, der Vollständigkeit wegen, dennoch hier noch mal kurz niederschreiben möchte.

Wir fügen unserem Paket-Manager nun einen neuen PGP-Schlüssel hinzu:

apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

Dem Paket-Manager apt fügen wir jetzt neue Quellen aus den offiziellen Docker-Repositorys für Debian hinzu:

cat > /etc/apt/sources.list.d/docker.list <<EOF
deb https://apt.dockerproject.org/repo debian-jessie main
EOF

Nun apts Paketliste auf den neuesten Stand bringen und die Docker Engine installieren:

apt-get update
apt-get install docker-engine

Anschließend noch den mitgelieferten Dienst starten:

service docker start

Erste Schritte mit Docker

Uns steht nun das Command Line Tool docker zur Verfügung, womit wir erste Gehversuche wagen wollen. Dazu laden wir uns mit dem Befehl docker pull zunächst ein nginx aus dem Image Repository Docker Hub, welches zum Ökosystem von Docker gehört. Bei dem eingesetzten Paket handelt es sich um das offizielle nginx Paket. Wir laden also das Image nginx. Mit einem Doppelpunkt lässt sich ein Tag und damit eine spezielle Version angeben, z.B. nginx:1.11. Bei undefiniertem Tag wird automatisch :latest angehangen, was einer Verknüpfung auf die letzte im Repository zur Verfügung stehenden Version entspricht. Damit lädt man unter Umständen später eine neuere Version als erwartet und erlebt eine böse Überraschung bei der Verwendung alter Konfigurationsdateien. Ich entscheide mich daher gleich :1.11 zu nutzen, um immer innerhalb des 1.11er Zweigs des Webservers zu bleiben.

docker pull nginx:1.11-alpine

Wie man an der Ausgabe in der Konsole nun gut erkennt, setzt sich ein solches Image aus mehreren Ebenen zusammen, die unabhängig von einander geladen werden können. Daraus ergibt sich natürlich auch ein Vorteil hinsichtlich zu ladender Updates dieses Images, weil nur der Unterschied, vergleichbar mit Git, geladen werden muss. Also ein erster Performance-Vorteil, der zu erkennen ist.

Einmal heruntergeladen, kann man sich die auf dem System befindlichen Images anschließend mit docker images anzeigen lassen. Ein Blick in die erzeugte Ausgabe geworfen:

REPOSITORY   TAG    IMAGE ID      CREATED       VIRTUAL SIZE
nginx        1.9    52d0c47f4ca7  5 days ago    132.8 MB

Eindeutig identifiziert wird das Image auf der Maschine über die Eigenschaft „Image ID“. Möchte ich das Image z.B. löschen, erledige ich das mit dem Befehl docker rmi (Remove Image).

docker rmi 52d0c47f4ca7

Das wollen wir in diesem Fall aber nicht, sondern dieses Image soll uns als Basis für unseren ersten Container dienen, den wir nun zum Laufen kriegen möchten. Wir starten unseren ersten Container mit dem Befehl docker run. Hierbei ist zu berücksichtigen, dass docker run bei Bedarf das Image auch direkt von Docker Hub herunterlädt, wenn es sich noch nicht auf der Maschine befindet.

docker run -d nginx:1.9

Führt ihr diesen Befehl in einer Virtuellen Maschine aus, könnte es aufgrund von fehlenden Kernel-Features durch den Hypervisor zu folgender Warnung kommen:

WARNING: Your kernel does not support memory swappiness capabilities, memory swappiness discarded.

Ein Kernel-Update bringt in diesem Fall also nichts. Die nicht genutzten Features sollen uns hier auch erstmal nicht weiter stören. Mit der Flag -d wird der Container im Hintergrund gestartet. Dass der Container läuft, können wir nachfolgend mit docker ps überprüfen.

CONTAINER ID    IMAGE        COMMAND                  CREATED             STATUS              PORTS               NAMES
57ff84ba3f21    nginx:1.9    "nginx -g 'daemon off"   3 seconds ago       Up 2 seconds        80/tcp, 443/tcp     sharp_yonath

Yeah, unser erster Container! Die Ernüchterung kommt aber recht schnell, denn der Container ist nun noch nicht von außen erreichbar. Dazu braucht es im Befehl docker run noch den zusätzlichen Parameter -P, der die Ports des Containers mit automatisch vergebenen High-Ports des Host-Systems verdrahtet. Zuvor stoppen wir den laufenden Container mit docker stop.

docker stop 57ff84ba3f21

Neuer Versuch: Wir starten den Container mit dem zusätzlichen Flag -P.

docker run -d -P nginx:1.9

Welche Ports des Host-Systems nun auf die genutzten Container-Ports 80 und 443 zeigen, entscheidet dabei die Docker Engine selbst. Ein schneller Blick mit docker ps in die Liste der laufenden Container, zeigt uns welche das sind.

CONTAINER ID    IMAGE       COMMAND                  CREATED            STATUS              PORTS                                           NAMES
d8431b5f8e42    nginx:1.11   "nginx -g 'daemon off"   36 seconds ago     Up 35 seconds       0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp   sick_newton

Nginx‘ Willkommensseite ist somit also über http://hostname:32769.

Im nächsten Teil lernen wir die Vorzüge von Docker Compose kennen. Damit werden wir ein komplexeres Setup bestehend aus einem PHP, MySQL und nginx aufbauen, wie es der Titel der Serie verspricht. Anschließend können wir damit unsere ersten dynamischen Inhalte ausliefern.

Update: Ich habe den verwendeten Tag nun an die aktuelle Version 1.11 (vorher 1.9) angepasst.

Patrick Baber

Als erfahrener Programmierer löst Patrick jeden Gordischen Knoten, findet die geeignete Methode und entwickelt damit flexible Software-Systeme.