Containerisierung einer Anwendung in Docker

Container sind die ideale Lösung um Einzelanwendungen separiert und abgeschottet in einer eigenen Umgebung ressourcensparend zu betreiben. Im Gegensatz zu virtuellen Maschinen, die einen eigenen Hypervisor voraussetzen, ein ganzes Betriebssystem ausführen und die gesamte Hardware emulieren müssen, sind Container da wesentlich genügsamer.
Eine der am weitesten verbreiteten Container-Lösungen heisst Docker. Auf dem offiziellen Docker-Hub gibt es bereits eine Vielzahl an vorgefertigten Container zur Auswahl, die von Webservern, Datenbanken, Cloud-Lösungen etc. kaum einen Wunsch offen lassen. Möchte man allerdings doch seine eigene, auf den persönlichen Bedarf abgestimmte Lösung erstellen und betreiben, kommt man nicht drumherum, selbst Hand an Docker anzulegen.
Wie dies funktioniert, wird im folgenden beschrieben.

Bevor in die Praxis übergegangen wird, sollten zuvor einige Begrifflichkeiten geklärt werden.

Was ist Docker

Docker ist eine Open-Source Software die auf einem regulärem Linux Betriebssytem installiert und ausgeführt werden kann. Mit ihr ist es möglich, Einzelanwendungen (z.B. Webserver, Management-Tools, Datenbanken, etc.) in einem, vom restlichen Betriebssystem, separierten Bereich zu betreiben. Dieser separierte Bereich wird durch die Docker Anwendung virtualisiert. Docker übernimmt hierbei die Zuweisung von Hardware-Ressourcen (wie CPU, RAM, Festplattenplatz etc.) und stellt sein eigenes Netzwerk-Interface bereit, damit die Anwendung nach außen hin erreichbar und kommunikationsfähig ist. Anders als eine virtuelle Maschine teilt sich Docker den Kernel des Wirt-Hosts. Außerdem stellt Docker eine CLI bereit, damit wir als Anwender mit den sogenannten ‘Docker-Containern’ und ‘Docker-Images’ kommunizieren zu können.
Die zuvor genannten Einzelanwendungen werden innerhalb von Docker-Containern betrieben. Doch um diese Docker-Container zu erstellen, müssen zuvor Docker-Images erstellt werden. Diese stellen sozusagen die ‘Blaupause’ eines Containers dar, die notwendig ist, um einen Container daraus zu erzeugen. Es lassen sich endlos viele Container aus einem Image erstellen.
Ein Docker Container ist dann die eigentlich lauffähige Umgebung, mit und auf der gearbeitet wird. Sie beinhaltet neben der bereitgestellten Anwendung ein eigenes Betriebssystem samt Paketabhängigkeiten und den zugehörigen Programmbibliotheken. Daher ist ein Docker Container auch problemlos auf anderen Linux Installationen betreibsfähig.

Installation von Docker

Nach dieser kleinen Einführung geht es hinüber in die Praxis, die als erstes die Installation von Docker vorsieht:

sudo apt update
sudo apt -y install docker.io

Docker bringt einen eigenen Daemon mit sich. Wir überprüfen ob dieser gestartet wurde und fügen ihn bei Bedarf dem Systemstart hinzu:

### Startet den Docker Dienst
sudo service docker start

### Fügt Docker dem Systemstart hinzu
sudo systemctl enable docker

Einen eigenes Docker-Image erzeugen

Um die Erstellung unseres Docker-Images zu steuern, legen wir uns ein Dockerfile an und zwar im Home-Verzeichnis …

cd ~
touch ./dockerfile

… und fügen dort folgenden Inhalt ein:

FROM ubuntu:22.04
 
ENV DEBIAN_FRONTEND=noninteractive

RUN apt update && \
  apt-get -y upgrade && \
  apt-get -y install ansible

Diese paar Zeilen reichen bereits aus, um auf Basis des vorgefertigten Ubuntu 22.04 Images (welches aus dem Internet von https://hub.docker.com bezogen wird), alle darin enthaltenen Pakete zu aktualisieren und Ansible zu installieren. Die Zeile ‘ENV DEBIAN_FRONTEND=noninteractive’ dorgt dafür, dass die Erzeugung unseres Images nicht durch eine Interaktive Frage unterbrochen bzw. gestört wird. Unser Image erstellen wir nun mit dem Befehl

sudo docker build -t mein_ansible:latest .

Sobald der darauffolgende Vorgang abgeschlossen ist, wurde lokal ein Image mit dem Namen ‘mein_ansible’ erzeugt. Die Angabe ‘:latest’ ist lediglich ein Tag (aus dem Englischen ‘label’, nicht die Zeitangabe) und hat soweit keinerlei technische Bewandnis.
Wir können uns unser Image Repertoire nun mit Hilfe der Docker CLI ansehen:

sudo docker image ls

Wir sehen unser Docker-Image, aus dem wir uns schlußendlich einen lauffähigen Container erstellen können, sowie das dazu verwendete ‘ubuntu 22.04’ Basis-Image.
Auf Grundlage dieses Images starten wir nun unseren ersten Container:

sudo docker run -dit mein_ansible:latest

Kein Feedback ist unter Linux positives Feedback und so sollte die Kommandozeile bei erfolgreicher Ausführung auch keinerlei Rückmeldung geben. Um auf Nummer sicher zu gehen, ob unser Container tatsächlich gestartet wurde, überprüfen wir dies mit:

sudo docker ps

Wir sehen hier auch, dass dem laufenden Container ein Fantasiename gegeben wurde. Um uns nun in diesen Container einzuloggen, geben wir diesen Namen im folgenden Befehl mit:

sudo docker exec -it wizardly_dewdney /bin/bash

Ändert den Namen (wizardly_dewdney) entsprechend eurer Container-Bezeichnung. Wir sollten uns nun als root im Container befinden und eine Bash-Shell als Eingabewerkzeug zur Verfügung haben. Von hier aus lässt sich der Container nach Lust und Laune bedienen um beispielsweise Dateien abspeichern zu können, wie dieses Ansible-Playbook:

mkdir -p /etc/ansible/playbooks

cat > /etc/ansible/playbooks/playbook.yml << EOF
---
- name: "Host-Fakten sammeln"
  hosts: vm-clients
  tasks:
EOF

Verlassen wir den Container mit …

exit

… und loggen uns erneut ein sehen wir, dass die zuvor angelegte Datei noch immer existiert.

Aus vorhandenen Containern ein Image erzeugen

Möchten wir nun einen Schritt weitergehen, können wir diesen Container mit allen darin getroffenen Änderungen abermals in ein neues Image speichern.
Hierfür setzen wir folgenden Befehl ausserhalb des Docker-Containers ab:

sudo docker commit wizardly_dewdney mein_ansible_update

Der Name des neuen Images lautet nun ‘mein_ansible_update’. Wir überzeugen uns, dass das neue Image entstanden ist.

sudo docker images -a

Tatsächlich ist ein neuer Eintrag der gewünschten Bezeichnung aufgetaucht.

Da wir unseren ‘alten’ Container nun nicht mehr benötigen, können wir ihn löschen. Damit dies gelingt, muss er zuvor gestoppt werden:

sudo docker stop wizardly_dewdney
sudo docker rm wizardly_dewdney

Nun starten wir in alter Manier den neuen Container und schauen nach, ob er auch tatsächlich die getroffenen Änderung mit an Bord hat (der Name ändert sich natürlich auch für den neu erzeugten Container):

sudo docker run -dit mein_ansible_update:latest
sudo docker exec -it modest_einstein /bin/bash
cat /etc/ansible/playbooks/playbook.yml

Und in der Tat, das zuvor angelegte Playbook erstrahlt in altem Glanz in der Kommandozeile!

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Nach oben scrollen