Wie auf einem Computer die Software Docker installiert wird, hat Robert in diesem Artikel bereits beschrieben:
Docker – Anwendungen und Systeme unter Linux virtualisieren / isolieren
Bislang habe ich ausschließlich VirtualBox genutzt, um virtuelle Maschinen aufzubauen und etwas auszutesten. Mit Docker verspreche ich mir die Möglichkeit, meine Tests auf kleine Füße zu stellen, um nicht immer mit Kanonen auf Spatzen zu schießen.
Um es vorweg zu nehmen: Aus meiner Sicht ist mein Wunsch in Erfüllung gegangen.
Es hat keinen Zweck sich darüber Gedanken zu machen, ob man die neueste Linuxdistribution in Docker testen kann. Grafischen Oberflächen kann man nicht nutzen – nur eben den Browser, wenn es bunt und anklickbar sein soll. Bedeutet, Docker ist was für serverseitige Programme.
Um mich dem Thema überhaupt nähern zu können, hatte ich mich auf Docker Hub umgesehen. In dem 6-teiligen Tutorial auf dem YouTube-Kanal von heise online gibt es einige gute Hinweise für die ersten Schritte und wo man eben die für Docker notwendigen Dinger (Images) bekommen kann.
Tatsächlich hat es dann etwas gedauert, bis ich die Images, Container und Volumens auseinanderhalten und verwalten konnte.
Natürlich bin ich ganz klein angefangen und habe die Konsolenbefehle gelernt. Damit weiß ich dann eben, was passiert, sollte ich später mit Docker-Compose (yaml-Script, mache ich jetzt) oder Portainer (eine grafischen Oberfläche für Docker) arbeite.
Heute habe ich für mich den ersten Teil meiner Lernphase für Docker abgeschlossen und kann nun via Docker-Compose ein Tool starten und die Anwendungsdaten in einem externen Volume speichern. Das Speichern der Anwendungdsdaten in den Containern ist suboptimal, weil sie schnell verloren gehen. Daher, wenn man Container produktiv einsetzen möchte, ist das Erlernen mit dem Umgang von Volumes wichtig. Diese Volumes gehören dann zwangsläufig in die Backup-Strategie des Computernutzters.
Meine Ausführungen werde ich über mehrere Artikel verteilen. Da wir hier im Wiki sind, bitte für Fragen und Anregungen ein entsprechendes Thema im Forum öffnen. Danke!
Im Docker Hub liegen offizielle Images von Docker und Images aus der Community. Bislang habe ich mich nur mit den offiziellen Images befast. Zum Lernen ist das wirklich ausreichend.
Natürlich wollte ich es mir so einfach wie möglichen machen. Mein Lernmaterial bezieht sich auf Ghost. Ghost ist eine freie Bloggingplattform. Ich kenne das Tool nicht, nur vom Namen her. Zu jedem Docker-Images gibt es eine Webseite, die Informationen zur weiteren Verwendung des jeweiligen Images bereithält.
Auf keinen Fall wollte ich etwas machen, wobei zwei Container gleichzeitig zu nutzen sind. Und nur auf der Konsole hantieren, wollte ich auch nicht.
Teil 1
Der Befehl zum Download des Docker-Images für Ghost ist auf der Webseite zu finden. Auf der Konsole ist der entsprechende Befehl auszuführen. Dieses muss man mit root-Rechten durchführen. Will man als Normaluser die Dockerbefehle ausführen, ist mit root-Rechten der User der Gruppe docker hinzuzufügen:
$ usermod -aG docker username
Nach einer Neuanmeldung kann der Normaluser ohne „sudo
“ arbeiten.
Der einfachste Befehl zum Download eines Images lautet:
$ docker pull ghost
Will man Ghost mit einer bestimmten Version nutzen bzw. ausprobieren, muss man mit sogenannten TAGS arbeiten. Diese TAGS beschreiben im Grunde genommen die Version bzw. die Versionsreihe. Dann könnte der pull-Befehl z.B. so aussehen, wenn es die neueste Version sein soll:
$ docker pull ghost:latest
Die Defaulteinstellung lautet wohl immer auf den TAG latest.
Nachdem der einfache Pull-Befehl abgesetzt ist, wird der Download gestartet und durchgeführt. Das Ergebnis sind wie folgt aus:
Using default tag: latest
latest: Pulling from library/ghost
e1acddbe380c: Pull complete
7263c7b7f332: Pull complete
0e985e216445: Pull complete
75a9268f63ec: Pull complete
15b30c5db6de: Pull complete
46e57f8bb6f3: Pull complete
76bb54f82d33: Pull complete
ef365ad3ce09: Pull complete
d9989d0de9cc: Pull complete
Digest: sha256:26e68af5cfe2902f7e1524bdb1ac77f1fcd6ffd462a990f80aff595008c1d926
Status: Downloaded newer image for ghost:latest
docker.io/library/ghost:latest
Der interessierte User wird sich nun fragen, wo denn der Download abgelegt wird. Wo liegt das Image?
Leider ist das nicht offensichtlich, denn im Downloadordner liegt es nicht.
Es liegt hier:
Aber das Images selber interessiert uns nicht, denn damit wird nur auf der Konsole (oder später in einer Docker-Compose-Datei) gearbeitet.
Es gibt sehr viele und unterschiedliche Dockerbefehle.
Nun haben wir einen pull-Befehl abgesetzt und ein Image heruntergeladen. Mit dem folgenden Befehl (incl. Ergebnis) kann man feststellen, ob es wirklich vorhanden ist und welche anderen Images es vielleicht noch gibt:
CODE: ALLES AUSWÄHLEN
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ghost latest b05a58075ef6 22 hours ago 448MB
In diesem Fall liegt derzeit nur ein Image auf dem Rechner, hat eine Größe von 448MB und ist vor 22 Stunden zuletzt aktualisiert worden (von den Entwicklern).
Als nächstes steht an, dass dieses Image irgendwie benutzbar gemacht werden muss. Um ein Image zu nutzen, muss der run-Befehl verwendet werden. Es gibt diverse Möglichkeiten, um einen run-Befehl zu kreieren. Es ist immer gut, auf der Webseite des Docker-Images nach der Ausführung des run-Befehls zu schauen.
Die einfachste Ausführung wäre
CODE: ALLES AUSWÄHLEN
$ docker run -d --name myghost ghost
Was steckt dahinter?
Der run-Befehl wird mit de Option -d gestartet sowie der Option –name gefolgt von einer Bezeichnung, die unser Container haben soll, nämlich myghost. Und zum Schluss kommt der Image-Name hinten dran.
Diesen Befehl setzen wir nicht ab, denn Ghost ist eine Webanwendung. Um eine Webanwendung auch wirklich im Browser starten zu können, muss der Befehl erweitert werden:
$ docker run -d --name myghost -e url=http://localhost:3001 -p 3001:2368 ghost
In die Adresszeile des Browsers ist später http://localhost:3001 (oder http://localhost:3001/ghost für Adminzugang) einzugeben.
Das Ergebnis der Befehlsausführung sieht wie folgt aus:
a92b1f1e260d72392c211a4d06c8855a6f5d096d0fd92ea7716267be6befd9e0
Mehr ist in der Tat nicht zu sehen, da die Option -d alles unsichtbar im Hintergrund ablaufen lässt.
Damit haben wir unseren ersten Container gestartet. Ob das wirklich so ist, und ob vielleicht noch mehr Container vorhanden sind, erfährt man hierüber:
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a92b1f1e260d ghost "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:3001->2368/tcp, :::3001->2368/tcp myghost
Mit folgendem Befehl werden die Container angezeigt, die gerade ausgeführt werden:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a92b1f1e260d ghost "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 0.0.0.0:3001->2368/tcp, :::3001->2368/tcp myghost
Das ist nahezu die gleiche Anzeige wie beim ls
-Befehl.
Damit haben wir ein Image heruntergeladen und einen Container gestartet. Das ein Image sowie ein Container vorhanden sind, können wir nun prüfen.
Das Ergebnis unserer Bemühungen sollte eine laufende Instanz von Ghost in unserem Browser sein:
Teil 2
Der erste Container läuft. Was man damit jetzt weiter macht, spielt im Moment noch keine Rolle.
Das Handling von Images und Containern ist noch nicht beendet, denn Container können gestoppt, gestartet und gelöscht werden. Letztlich können Images nur gelöscht werden, wenn man sie nicht mehr benötigt.
Um einen Container zu stoppen, könnte man so vorgehen:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a92b1f1e260d ghost "docker-entrypoint.s…" 26 minutes ago Up 26 minutes 0.0.0.0:3001->2368/tcp, :::3001->2368/tcp myghost
$ docker stop a92b1f1e260d
a92b1f1e260d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1. Mit dem ersten Befehl wird geprüft, ob der zu stoppende Container überhaupt läuft.
2. Der zweite Befehl stoppt die Ausführung des Container über seine ID.
3. Mit dem dritten Befehl wird das Ergebnis der Bemühungen überprüft.
Das Ergebnis ist, dass der Container nicht mehr aktiv ist.
Natürlich kann man einen Container auch wieder starten. Das sieht dann wie folgt aus:
$ docker start a92b1f1e260d
a92b1f1e260d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a92b1f1e260d ghost "docker-entrypoint.s…" 29 minutes ago Up 1 second 0.0.0.0:3001->2368/tcp, :::3001->2368/tcp myghost
Damit ist der Container wieder aktiv und ebenfalls lässt sich die Webseite wieder anzeigen.
Der letzte Befehl, der noch im Handling der Container wichtig ist, betrifft das Löschen. Damit ein Container gelöscht werden kann, muss er stoppt sein. Ingesamt kann das so ablaufen:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a92b1f1e260d ghost "docker-entrypoint.s…" 32 minutes ago Up 2 minutes 0.0.0.0:3001->2368/tcp, :::3001->2368/tcp myghost
$ docker stop a92b1f1e260d
a92b1f1e260d
$ docker container rm a92b1f1e260d
a92b1f1e260d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1. Prüfung, ob der zu löschende Container aktiv ist.
2. Wenn ja, wird der Container gestoppt.
3. Dann wird der Container gelöscht.
4. – 6. Es wird geprüft, ob der Container noch vorhanden ist (ich nutze meist Befehl Nr. 6 nach dem Löschen).
Der Container ist nun weg. Geblieben ist das Image. Denn mit dem Image kann man jederzeit einen neuen Container erstellen (run-Befehl).
Wären in dem Container Anwendungsdaten vorhanden gewesen, so wären sie jetzt weg. Sobald der Container gelöscht wird, sind auch die Anwendungsdaten gelöscht. Gestoppte Container behalten die Daten.
Generell sollte man in Containern keine Anwendungsdaten speichern. Diese Daten gehören in ein Volume, das außerhalb des Containers liegt.
Das Löschen von Images wird zu einem späteren Zeitpunkt behandelt.
Teil 3
Anwendungsdaten können gespeichert werden. Allerdings nicht im Container, da gehören sie nicht hin, sondern dafür verwendet man Volumes.
Der generelle Befehl zum Anlegen eines Volumes lautet wie folgt:
$ docker volume create
Mit diesem Befehl wird ein Volume angelegt, dessen „Name“ aus zufälligen Ziffern und Buchstaben besteht und ellenlang ist.
Es wäre schon besser, wenn man dem Kind einen Name gibt:
$ docker volume create meinvolume
Der letzte Teil des Befehls „meinvolume“ ist nun der Name des Volumes. Ob Volumes vorhanden und wie sie benannt sind, lässt sich wie folgt feststellen:
$ docker volume create meinvolume
meinvolume
$ docker volume ls
DRIVER VOLUME NAME
local 0bf98e29f96b7bf612a0b183bc4b43007142f3244eb3e9cd0033dae29f92ee57
local 445e2c5a1e8f0b7319bca133189a910ce388566bec53968f87adfb8ee1e2f640
local a36d2c024a46485c50549b59a6da30da3d110530d9555c3e92a02bff9e0adb3c
local meinvolume
Aus meiner Sicht ist der lesbare Volumenname angenehmer als die 3 bereits bestehenden Volumes aus meiner Testphase, die ich absichtlich habe bestehen lassen. Natürlich lassen sich, analog zu Images und Containern, Volumens löschen.
Die Volumes werden im Hostsystem abgelegt und können ganz normal benutzt werden. Wie bereits weiter oben angedeutet, sind diese Volumes durchaus in die Sicherungsroutinen einzubauen, wenn wichtige Daten in den Volumens erzeugt und gehalten werden. Die Volumens liegen standardmäßig hier:
Bitte beachten, dass auch ein in der Gruppe docker angelegter Normaluser den Ordner docker nicht sieht. Hier muss mit sudo gearbeitet werden.
Volumens enthalten die Anwendungsdaten. Natürlich muss man beim Löschen von Volumens aufpassen. Im Grunde genommen ist das nichts anderes wie das Löschen der eigenen Systemfestplatte.
Folgender Befehl löscht ein Volume:
$ docker volume rm meinvolume
meinvolume
$ docker volume ls
DRIVER VOLUME NAME
local 0bf98e29f96b7bf612a0b183bc4b43007142f3244eb3e9cd0033dae29f92ee57
local 445e2c5a1e8f0b7319bca133189a910ce388566bec53968f87adfb8ee1e2f640
local a36d2c024a46485c50549b59a6da30da3d110530d9555c3e92a02bff9e0adb3c
Mit dem ersten Befehl wurde das Volume gelöscht. Mit dem zweiten Befehl wurde überprüft, ob das Volume tatsächlich gelöscht wurde.
Es ist nicht wirklich vorteilhaft, wenn die Volumes irgendwo in den Tiefen des Systems versteckt liegen. Es macht Sinn, dass man eine Struktur aufbaut, die alle Volumes beinhaltet und somit auch einfach in die Sicherungsroutinen eingefügt werden kann.
Dazu lenkt man das Volume an einen definierten Ort. Im Home-Verzeichnis meines Users habe ich einen Ordner dockerdata sowie einen Unterordner ghost angelegt. Ich möchte erreichen, dass die Anwendungsdaten im Unterordner gespeichert werden. Dort kann ich sie jederzeit sehen und benutzen wie alle anderen Daten auch.
Das Verlinken des Volumes auf den Unterordner ghost kann während der Ausführung des run-Befehls erfolgen. Das sieht dann sehr kryptisch aus:
docker run -d --name myghost -e url=http://localhost:3001 -p 3001:2368 -v ~/dockerdata/ghost:/var/lib/ghost/content ghost
Wie mit dem run-Befehl ein Container erzeugt wird, wurde weiter oben schon beschrieben. Der aktuelle Befehl wurde um den Zusatz
erweitert. Die Option –
v
steht für Volume. Hinter dem Doppelpunkt wird der Originalort angegeben, an dem das Volume liegt.
In dem Unterordner ghost unter /home/django/dockerdata wurden nun weitere Ordner angelegt:
Alle Anwendungsdaten, die von nun an in Ghost erstellt oder hingebracht werden, werden in diesen Ordnern gespeichert.
Ich habe mich als Admin angemeldet und einen ersten Artikel geschrieben, in dem ein Bild eingefügt wurde. Dieses Bild wird im Unterordner images abgelegt.
Auf der Webseite ist das Ergebnis der Artikelerstellung auch zu bewundern:
Teil 4
Das Arbeiten in/auf der Konsole macht durchaus Spaß. Das Handling von Images, Containern und Volumes in der einfachsten Art und Weise, wie bislang beschrieben, ist eine wichtige Grundlage zum Kennenlernen von Docker und seinen vielen Möglichkeiten.
Aber man muss auch die Zeit bedenken, die es kostet, immer wieder diese Befehle einzutippen. Inbesondere die Aktionen aus Teil 3 lassen sich sehr gut automatisieren. Und das funktioniert mit docker-compose.
Bei der Installation von Docker wird dieses Tool nicht installiert. Es lässt sich aber ganz flott nachinstallieren:
sudo apt-get install docker-compose
Die 3 wichtigsten Befehle von docker-compose sind:
1. docker-compose up -d
2. docker-compose stop
3. docker-compose down
Mit dem ersten Befehl wird das Tool im Hintergrund gestartet. Der zweite Befehl stoppt das Tool. Der dritte Befehl fährt das Tool herunter. Sobald das erfolgt, wird auch sofort der Container, der beim Start erzeugt wurde, gelöscht. Man muss eigentlich als User nichts mehr machen, um im Container zu arbeiten bzw. die Arbeit mit dem Container zu beenden. Das macht eben docker-compose.
Das funktioniert aber alles nur, wenn eine entsprechende Konfigurationsdatei vorhanden ist. Diese Konfigurationsdatei muss den Namen docker-compose.yaml haben, sonst läuft docker-compose nicht. Die Einrückungstiefe der Programmzeilen sollte mit je zwei Leerzeichen erfolgen. Tabs gehe auch, können aber Problem verursachen.
Der Inhalt der Datei ist nun so aufgebaut, dass das gleiche erreicht wird, wie in den obigen Beschreibungen dargestellt. So sieht es aus:
version: ‚3.1‘
services:
meinghost:
image: ghost
restart: always
ports:
– 8081:2368
volumes:
– ./ghost:/var/lib/ghost/content
environment:
url: http://localhost:8081
Die Ausführung von docker-compose zum Start des Tools ist dann wie folgt vorzunehmen:
$ docker-compose up -d
Creating network "dockerdata_default" with the default driver
Creating dockerdata_meinghost_1 ... done
Es wird bei der Ausführung ein Default-Netzwerk eingerichtet. Auch Netzwerke kann man in Docker wie Images, Container und Volumes selber erstellen und verwalten. In dem Script ist das aber nicht erfolgt, daher wird ein Default-Netzwerk ausgeführt.
Ob die Ausführung des Befehl gelungen ist, zeigt wieder eine Überprüfung der laufenden Container:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3311a4b8aa24 ghost "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 0.0.0.0:8081->2368/tcp, :::8081->2368/tcp dockerdata_meinghost_1
52e8545e09eb ghost "docker-entrypoint.s…" 32 minutes ago Up 32 minutes 0.0.0.0:3001->2368/tcp, :::3001->2368/tcp myghost
Hier ist zu sehen, dass zwei Container laufen. Der erste Container ist der mit docker-compose erzeugte Container, der auf Port 8081 läuft. Der zweite Container ist der vorhin erstellte Container, der auf Port 3001 gelegt wurde.
Auch der mit dem Script erzeugte Container nutzt das vorhandene Volume und zeigt die gleiche Webseite an.
Egal, was mit den Containern passiert, solange das Volume unangetastet bleibt, kann man mit jedem Container auf das Volume zugreifen. Allerdings muss man beim Wechsel des Image aufpassen. Man kann nicht einfach so eine andere Version des Images nutzen. Dazu später irgendwann mal mehr.
Verfasst von Bommo
Noch keine Reaktion