Bisher kam in diesem Workshop das von Docker-Hub heruntergeladene Image "fedora" zum Einsatz. Dieses können Sie nun als Grundlage für Ihr erstes eigenes Image verwenden. Grundsätzlich haben Sie zwei Möglichkeiten, um Ihre Änderungen an einem Container in einem neuen Image zu zementieren. Entweder Sie führen die Änderungen interaktiv in einem Container durch und comitten sie dann im Anschluss oder aber Sie erzeugen ein Dockerfile, in dem Sie alle gewünschten Änderungen an einem Image aufführen und danach einen Build-Prozess anstoßen. Die erste Methode skaliert nicht wirklich gut und ist eigentlich auch nur für erste Tests geeignet oder um schnell ein neues Image auf Basis bereits getätigter Änderungen durchzuführen, weshalb an dieser Stelle lediglich die Dockerfile basierte Variante vorgestellt wird.
Ein Dockerfile muss alle Anweisungen enthalten, die notwendig sind, um ein neues Image zu erzeugen. Dazu gehört beispielsweise, welches Basis-Image als Grundlage dient, welche zusätzliche Software benötigt wird, wie das Netzwerk-Portmapping aussehen soll, und natürlich auch einige Metainformationen, also beispielsweise, wer dieses Image erzeugt hat. Die Manpage "Dockerfile" enthält sämtliche zulässigen Anweisungen. Schauen Sie sich diese ruhig einmal an, bevor Sie weitere Images bauen. Das Listing 3 zeigt ein einfaches Beispiel für ein Dockerfile, welches das bestehende Fedora-Image aktualisiert, einen Webserver installiert und den Webserver-Port 80 der Außenwelt zur Verfügung stellt. Speichern Sie die Datei unter dem Namen "Dockerfile" ab.
Den eigentlichen Build-Vorgang starten Sie mit dem Kommando docker build. Achten Sie an dieser Stelle darauf, dass das Kommando in dem Verzeichnis aufgerufen wird, in dem Sie zuvor das Dockerfile abgespeichert haben (Listing 4).
Listing 4: Docker-Build
# docker build -t fedora_httpd. Uploading context 50.72 MB Uploading context Step 0 : FROM fedora ---> 7d3f07f8de5f Step 1 : MAINTAINER Thorsten Scherf ---> Running in e352dfc45eb9 ---> f66d1467b2c2 Removing intermediate container e352dfc45eb9 Step 2 : RUN yum update -y ---> Running in 259fb5959f4e [...] Step 3 : RUN yum install httpd -y ---> Running in 82dc46f6fc45 [...] Step 4 : RUN bash -c 'echo "Hello again..." > /var/www/html/index.html' ---> Running in e1fdb6433117 ---> d61972f4d053 Removing intermediate container e1fdb6433117 Step 5 : EXPOSE 80 ---> Running in 435a7ee13c00 ---> e480337fe56c Removing intermediate container 435a7ee13c00 Step 6 : ENTRYPOINT [ "/usr/sbin/httpd" ] ---> Running in 505568685b0d ---> 852868a93e10 Removing intermediate container 505568685b0d Step 7 : CMD [ "-D", "FOREGROUND" ] ---> Running in cd770f7d3a7f ---> 2cad8f94feb9 Removing intermediate container cd770f7d3a7f Successfully built 2cad8f94feb9
Dabei können Sie gut beobachten, wie Docker die einzelnen Anweisungen aus dem Dockerfile abarbeitet und jede Anweisung in einem neuen temporären Container resultiert. Dieser wird committet und anschließend wieder entfernt. Das Endresultat ist schließlich ein neues Image, das aus einer ganzen Reihe neuer Layer besteht. Rufen Sie
»docker images
«
auf, sehen Sie neben dem bereits bekannten "fedora"-Image ein zweites Image mit dem Namen "fedora_httpd". Das ist der Name, den Sie zuvor beim Build-Prozess festgelegt haben.
Möchten Sie einen neuen Container auf Basis des soeben erzeugten Images starten, rufen Sie Docker wie folgt auf:
# docker run -d --name="www1" -P fedora_httpd -n "fedora_webserver"
Die neue Option "-P" sorgt dafür, dass Docker den Webserver-Port des Containers an einen zufälligen hohen Netzwerkport des Hosts bindet. Welcher Port das ist, ist wieder in der Ausgabe von
»docker ps
«
sichtbar. Alternativ dazu können Sie natürlich auch den folgenden Aufruf verwenden, um das verwendete Netzwerk-Mapping herauszubekommen:
# docker inspect -f '{{.Network-Settings.Ports}}' www1
map[80/tcp:[map[HostIp:0.0.0.0 HostPort:49154]]]
Wollen Sie stattdessen wieder auf einen statischen Port mappen, verwenden Sie die Option "-p 8080:80" beim Aufruf von
»docker run
«
. Hier wird der Webserver-Port 80 an den Port 8080 des Hosts gebunden. Um die korrekte Funktion des Webservers zu prüfen, rufen Sie erneut "wget" auf:
# wget -nv -O - localhost:49154
Hello again...
Hat alles funktioniert, haben Sie hiermit erfolgreich Ihr erstes Docker-Image erzeugt und getestet. Natürlich können Sie nun das erfolgreich getestete Image exportieren, auf einen anderen Host kopieren und es dort importieren. Gerade diese Portabilität ist ja einer der großen Vorteile von Docker. Der Export gelingt beispielsweise mit dem folgenden Kommando:
# docker save fedora_httpd > fedora_httpd.tar
Nachdem das Archiv auf den Zielhost kopiert wurde, können Sie es dort importieren und optional mit einem neuen Namen versehen:
# cat fedora_httpd.tar | docker import - tscherf/fedora_httpd
Ab jetzt steht dieses Image auf einem zusätzlichen Host zur Verfügung und kann hier unmittelbar zum Einsatz kommen. Eine Anpassung der Umgebung ist hierfür nicht mehr notwendig. Erzeugen Sie nun auf Basis des neuen Images einen neuen Container, läuft die Anwendung auf dem zweiten Host genauso ab wie auf dem Host, auf dem Sie das Image getestet haben. Mit
»docker rmi Image
«
können Sie übrigens nicht mehr benötigte Images wieder entfernen. Achten Sie nur darauf, dass kein Container mehr auf das zu löschende Image zurückgreift.
Nach der Lektüre dieses Docker-Workshops sollten Sie in der Lage sein, eine Docker-Umgebung zu installieren und zu konfigurieren. Bestehende Images können Sie vom zentralen Docker-Hub herunterladen. Sie wissen, wie diese in einem Container gestartet und von außen erreichbar gemacht werden. Bestehende Images können Sie nun ebenfalls an Ihre Umgebung anpassen und daraus wieder neue Images erzeugen.
Eine interessante Frage ist, wie Sie selbst erzeugte Images auf dem zentralen Docker-Hub zur Verfügung stellen können und auch wie Sie mittels Links eine Verbindung zwischen verschiedenen Containern herstellen. Dies ist gerade dann interessant, wenn Sie beispielsweise einen Container mit einem Webserver laufen haben, der über eine sichere Verbindung mit einer Datenbank in einem anderen Container kommunizieren soll. Die Docker-Webseite [4] stellt hierzu nützliche Informationen zur Verfügung.
(of)
Link-Codes
[1] Docker Installation: http://docs.docker.com/installation/
[2] Device-Mapper Backend README: https://github.com/docker/docker/blob/master/daemon/graphdriver/devmapper/README.md
[3] Docker Networking: https://docs.docker.com/articles/networking/
[4] Docker-Webseite: https://www.docker.com/