Schlagwort-Archive: Docker

Besser als XAMPP: Docker-basierte Entwicklungsumgebung

Traditionelle lokale Entwicklungsumgebungen wie XAMPP sind seit Jahren beliebt, da sie einfach einzurichten und zu verwenden sind. Allerdings stoßen sie schnell an ihre Grenzen, wenn es um Platzersparnis, Geschwindigkeit und Flexibilität geht. Hier kommt eine Docker-basierte Lösung ins Spiel, die XAMPP in vielerlei Hinsicht überlegen ist.

Platzersparnis und Geschwindigkeit

Mit Docker können Entwicklungsumgebungen schlank gehalten werden. Der gesamte Stack – bestehend aus Apache, MariaDB und Mailhog – wird in einem einzigen Container betrieben. Das spart nicht nur Speicherplatz, sondern sorgt auch für eine bemerkenswerte Steigerung der Geschwindigkeit. Der Start der gesamten Umgebung dauert nur wenige Sekunden, im Gegensatz zu den längeren Ladezeiten bei XAMPP.

Einfachheit des Buildings

Das Building eines Docker-Containers ist einfach und schnell erledigt. Mit einem einzigen Befehl wird der komplette Stack erstellt und konfiguriert. Im Gegensatz zu XAMPP müssen keine zusätzlichen Softwarepakete heruntergeladen und installiert werden. Eine Datei (dockerfile) regelt alle notwendigen Installationen und Konfigurationen:

FROM debian:latest

RUN apt-get update && apt-get install -y apache2 mariadb-server mailhog supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY init.sh /usr/local/bin/init.sh
RUN chmod +x /usr/local/bin/init.sh

CMD ["/usr/bin/supervisord"]

In diesem Dockerfile werden die Anweisungen zum Erstellen eines Docker-Containers beschrieben, der auf einem Debian-basierten Betriebssystem läuft und verschiedene Dienste wie Apache, MariaDB und Mailhog enthält. Hier ist eine Erklärung, was in jedem Schritt passiert:

1. FROM debian:latest

  • Beschreibung: Legt das Basis-Image fest, auf dem der Container aufbaut. In diesem Fall wird die neueste Version des Debian-Betriebssystems verwendet.

2. RUN apt-get update && apt-get install -y apache2 mariadb-server mailhog supervisor

  • Beschreibung: Führt zwei Befehle in einer Zeile aus:
  1. apt-get update: Aktualisiert die Liste der verfügbaren Pakete und deren Versionen.
  2. apt-get install -y apache2 mariadb-server mailhog supervisor: Installiert die Pakete apache2 (Webserver), mariadb-server (Datenbankserver), mailhog (E-Mail-Testing-Tool) und supervisor (Prozesssteuerungstool). Der Schalter -y bestätigt automatisch alle Aufforderungen zur Installation der Pakete.

3. COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

  • Beschreibung: Kopiert die Datei supervisord.conf aus dem lokalen Verzeichnis in das Verzeichnis /etc/supervisor/conf.d/ im Container. Diese Datei enthält Konfigurationen für Supervisor, um die Dienste zu steuern, die im Container ausgeführt werden sollen.

4. COPY init.sh /usr/local/bin/init.sh

  • Beschreibung: Kopiert das Skript init.sh in das Verzeichnis /usr/local/bin/ im Container. Dieses Skript wird später zur Initialisierung der Dienste verwendet.

5. RUN chmod +x /usr/local/bin/init.sh

  • Beschreibung: Ändert die Berechtigungen der Datei init.sh, um sie ausführbar zu machen. Dies ist notwendig, damit das Skript später im Container ausgeführt werden kann.

6. CMD ["/usr/bin/supervisord"]

  • Beschreibung: Legt den Standardbefehl fest, der ausgeführt wird, wenn der Container gestartet wird. In diesem Fall wird supervisord ausgeführt, um die in supervisord.conf definierten Dienste (wie Apache, MariaDB und Mailhog) zu starten und zu überwachen.

Zusammengefasst erstellt dieses Dockerfile einen Container, der auf Debian basiert, die benötigten Pakete installiert, Konfigurationsdateien kopiert und Supervisor verwendet, um die verschiedenen Dienste im Container zu verwalten.

Schnelleres Deployment

Mit Docker wird das Deployment zur Leichtigkeit. Es ist möglich, die gesamte Umgebung in kürzester Zeit auf einem anderen System zu replizieren. Es genügt, den Container auf einem anderen Rechner zu starten, und die Entwicklungsumgebung ist sofort einsatzbereit – ohne zusätzliche Installationen und Konfigurationen. Die Dateien build-container.bat und start-container.bat sorgen für einen nahtlosen Startprozess.

Den Build starten

Die build-container.bat Datei ist ein Batch-Skript für Windows, das verwendet wird, um das Docker-Image zu erstellen. Hier ist eine Erklärung, was in dieser Datei passiert:

Inhalt von build-container.bat

docker build -t my-fullstack-app .
Erklärung
  • docker build -t my-fullstack-app .
  • docker build: Dieser Befehl erstellt ein Docker-Image aus einem Dockerfile.
  • -t my-fullstack-app: Mit dem -t (Tag) Flag wird ein Name und optional ein Tag für das erstellte Image angegeben. In diesem Fall wird das Image als my-fullstack-app benannt.
  • .: Der Punkt gibt das Verzeichnis an, in dem das Dockerfile liegt. In diesem Fall ist es das aktuelle Verzeichnis.

Das Skript baut ein Docker-Image namens my-fullstack-app aus dem Dockerfile im aktuellen Verzeichnis. Sobald dieser Befehl ausgeführt wird, durchläuft Docker die Schritte im Dockerfile, um das Image zu erstellen. Dieses Image kann dann verwendet werden, um Container zu starten.

Gleichzeitige Entwicklung und Testing

Ein weiterer Vorteil der Docker-basierten Umgebung ist die Möglichkeit, lokale Änderungen in Echtzeit zu verfolgen. Die Daten werden direkt von einem lokalen Verzeichnis in den Container gemountet:

docker run -d -p 8080:80 my-fullstack-app

Damit werden Änderungen sofort übernommen, ohne dass der Container neu gebaut werden muss. Das bedeutet effizienteres Arbeiten und schnelleres Testen von neuen Funktionen.

Vorteile der Verwendung einer Batch-Datei für docker run

Die Verwendung einer Batch-Datei für den docker run Befehl bietet mehrere Vorteile, insbesondere für Entwickler, die sich einen effizienteren und konsistenteren Workflow wünschen:

  1. Wiederholbarkeit: Mit einer Batch-Datei können Sie den Container jederzeit mit den exakt gleichen Parametern starten. Das verhindert Fehler, die bei der manuellen Eingabe des Befehls passieren können.
  2. Zeitersparnis: Anstatt sich jedes Mal an alle notwendigen Parameter und Optionen zu erinnern, können Sie den Container mit einem einzigen Doppelklick oder einem kurzen Befehl im Terminal starten. Das spart wertvolle Zeit.
  3. Konsistenz: Durch die Automatisierung des Startvorgangs stellen Sie sicher, dass der Container immer in der gleichen Umgebung läuft, was für die Entwicklung und Fehlersuche sehr wichtig ist.
  4. Leichteres Deployment: Wenn Sie den Container auf einem anderen System starten möchten, können Sie die Batch-Datei einfach weitergeben. Der Empfänger muss lediglich die Datei ausführen, ohne sich um die genauen Details des docker run Befehls kümmern zu müssen.

Aufbau der start-container.bat

Die Batch-Datei start-container.bat enthält den folgenden Befehl:

@echo off
docker run -d -p 8080:80 -p 3306:3306 -p 8025:8025 -p 1025:1025 -v %cd%/src:/var/www/html my-fullstack-app
Was passiert hier?
  • Automatischer Start des Containers: Der docker run Befehl startet den Container my-fullstack-app. Durch das -d Flag wird der Container im Hintergrund ausgeführt.
  • Port-Mapping: Mit den -p Optionen werden die Ports des Hostsystems mit denen des Containers verknüpft. Dadurch werden der Webserver, die Datenbank und Mailhog korrekt verfügbar gemacht.
  • Direkter Zugriff auf den Quellcode: Das -v Flag sorgt dafür, dass das lokale Verzeichnis ./src in den Container gemountet wird. Dadurch werden Änderungen an den Dateien in ./src sofort im Container sichtbar, was die Entwicklungszeit verkürzt.
  • Einfache Ausführung: Durch die Batch-Datei muss man sich nicht die genauen Befehle und Parameter merken. Ein Doppelklick auf die Datei reicht, um den Container mit allen benötigten Einstellungen zu starten.

Die Batch-Datei vereinfacht und beschleunigt den Entwicklungsprozess erheblich. Sie ermöglicht es, den Docker-Container mit einem einzigen Klick oder Befehl im Terminal zu starten und stellt sicher, dass der Container immer mit den korrekten Einstellungen ausgeführt wird. Dies ist besonders praktisch, wenn Sie mehrere Projekte oder Umgebungen verwalten und immer wieder die gleichen Schritte ausführen müssen.

Einfache Einarbeitung

Die Einarbeitung in Docker ist genauso einfach, wenn nicht sogar einfacher, als der Einstieg in XAMPP und andere lokale Entwicklungsumgebungen. Mit gut dokumentierten Dateien wie init.sh, die sich um die automatische Konfiguration von Diensten wie Apache und MariaDB kümmert, wird der Einstieg erleichtert:

#!/bin/bash

# bind-address ändern auf 0.0.0.0, um remote Zugriff zu ermöglichen
sed -i 's/^bind-address\s*=.*$/bind-address = 0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf

# Starte MariaDB
service mariadb start

# Warte darauf, dass MariaDB bereit ist
until mysqladmin ping &>/dev/null; do
  echo "Warte auf MariaDB..."
  sleep 1
done

# Erstelle Datenbank und Benutzer
# erstellt User: user1 mit Passwort: Geheim123
mysql -e "CREATE USER IF NOT EXISTS 'user1'@'%' IDENTIFIED BY 'Geheim123';"
mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'user1'@'%';"
mysql -e "FLUSH PRIVILEGES;"

# Apache Konfiguration automatisch anpassen
sed -i 's/DirectoryIndex .*/DirectoryIndex index.php index.html/' /etc/apache2/mods-enabled/dir.conf

# Apache neu starten, um die Änderungen zu übernehmen
service apache2 restart

Der Supervisor-Dienst

Die supervisord.conf Datei konfiguriert den Supervisor-Dienst, der im Container verwendet wird, um mehrere Prozesse gleichzeitig zu starten und zu überwachen. Supervisor ist ein Prozesssteuerungswerkzeug, das hilfreich ist, um sicherzustellen, dass Dienste wie Apache, MariaDB und Mailhog kontinuierlich im Container laufen.

[supervisord]
nodaemon=true

[program:apache2]
command=/usr/sbin/apache2ctl -D FOREGROUND
autostart=true
autorestart=true
stdout_logfile=/var/log/apache2.log
stderr_logfile=/var/log/apache2_err.log

[program:mariadb]
command=/usr/bin/mysqld_safe
autostart=true
autorestart=true
stdout_logfile=/var/log/mariadb.log
stderr_logfile=/var/log/mariadb_err.log

[program:mailhog]
command=/usr/local/bin/MailHog
autostart=true
autorestart=true
stdout_logfile=/var/log/mailhog.log
stderr_logfile=/var/log/mailhog_err.log

Erklärung der Abschnitte
  1. [supervisord]:
    • nodaemon=true: Führt Supervisor im Vordergrund aus, was in einem Docker-Container erforderlich ist, damit der Container nicht sofort beendet wird.
  2. [program:apache2]:
    • command=/usr/sbin/apache2ctl -D FOREGROUND: Startet den Apache-Webserver im Vordergrundmodus.
    • autostart=true: Startet Apache automatisch, wenn der Container gestartet wird.
    • autorestart=true: Startet Apache automatisch neu, falls es unerwartet beendet wird.
    • stdout_logfile und stderr_logfile: Speichert die Standardausgabe und Fehlerausgabe von Apache in Log-Dateien.
  3. [program:mariadb]:
    • command=/usr/bin/mysqld_safe: Startet den MariaDB-Dienst im sicheren Modus.
    • Die anderen Optionen sind ähnlich wie bei Apache und sorgen dafür, dass MariaDB automatisch gestartet und überwacht wird.
  4. [program:mailhog]:
    • command=/usr/local/bin/MailHog: Startet den MailHog-Service, der zum Testen von E-Mails verwendet wird.
    • Die weiteren Optionen entsprechen denen für Apache und MariaDB und sorgen für den automatischen Start und Neustart von MailHog.

Durch die Verwendung von Supervisor wird sichergestellt, dass alle drei Dienste (Apache, MariaDB, und MailHog) im Container parallel laufen und überwacht werden. Wenn einer dieser Dienste abstürzt, wird er automatisch neu gestartet, was die Zuverlässigkeit des Containers verbessert.

Die Dateien in der Übersicht

Hier ist eine Übersicht der Verzeichnisstruktur und Dateien:

/project-directory
│
├── build-container.bat
├── dockerfile
├── init.sh
├── start-container.bat
├── supervisord.conf
├── src/
│   └── (die Webanwendungsdateien)
  • build-container.bat: Skript zum Bauen des Docker-Containers.
  • dockerfile: Definiert die Container-Umgebung und installierte Software.
  • init.sh: Initialisierungsskript, das während des Container-Starts ausgeführt wird.
  • start-container.bat: Skript zum Starten des Docker-Containers mit den benötigten Ports und Volumes.
  • supervisord.conf: Konfigurationsdatei für Supervisor, um Dienste wie Apache, MariaDB und Mailhog zu verwalten.
  • src/: Verzeichnis, das die Quellcodes deiner Webanwendung enthält.

Fazit

Im Vergleich zu XAMPP bietet eine Docker-basierte Entwicklungsumgebung zahlreiche Vorteile. Sie ist platzsparender, schneller im Start und Betrieb, einfacher zu konfigurieren und erleichtert das Deployment. Die Investition in die Einarbeitung lohnt sich, denn sie ermöglicht effizienteres Arbeiten und schnellere Entwicklungsprozesse.

Docker Container – Anlegen, Starten, Verändern

Hier zeige ich kurz und schnell auf, wie man Docker Container anlegt, startet und editiert.

Anmerkung: Ich nutze Windows 10 als Host und arbeite mit Docker Desktop und der Linuxumgebung für Windows namens WSL bzw. WSL2. Diese Befehle funktionieren aber selbstverständlich auch auf nativen Linux-Systemen.

Ein Image herunterladen

Docker Container sind selbstständig lauffähige Instanzen von Images, die editiert, dupliziert, getestet, verschickt oder (später) wieder entfernt werden können. Um also einen Container zu starten, muss man zunächst ein Image anlegen oder herunterladen. Dazu kann man etwa das Repository von docker.com, das Docker Hub, benutzen. (Später wird noch gezeigt, wie man Images selbst erstellen kann.) Das Image verbleibt als Blaupause dabei unverändert.

Im Online Docker Hub gibt es tausende verschiedener Images. Ich nutze hier das thematisch naheliegende Image „docker/getting-started“.

Wir geben in der Kommandozeile ein:

cd ~ # ab ins Homeverzeichnis
docker pull docker/getting-started

Folgendes sollte zu sehen sein:

docker pull docker/getting-started

Um zu überprüfen, welche Images in unserem lokalen Repository vorhanden sind, nutzen wir das Kommando docker images.

docker images
docker images

Den ersten Container erstellen

Nur erstellen wir unseren ersten einfachen Container.

Da es anfangs zu Missverständnissen führen kann, weil man fälschlicherweise die Befehle run und start als Synonyme versteht, muss ich auf den entscheidenden Unterschied hinweisen: run = Abkürzung für create + start

Daher macht

docker create <image_id>
docker start <container_id>

dasselbe wie

docker run <image_id>

Der Befehl run erzeugt also einen neuen Container von einem Image und startet ihn automatisch.

Wir gehen einmal Schritt für Schritt vor.

docker create -p 80:80 docker/getting-started # Container wird angelegt, aber nicht gestartet
docker ps -a # Auflistung der vorhandenen Container

Mit „-p 80:80“ werden die Ports 80 von Container und Gastsystem miteinander verbunden, das ist wichtig, um gleich per Browser auf den Container zugreifen zu können. Wie gewünscht und erwartet wurde ein neuer Container angelegt. Nun wollen wir diesen starten. (Wir können Container über deren automatisch generierten Namen ansprechen.)

docker start eloquent_haslett # Namen kann man leichter nutzen als IDs
docker ps -a # Kontrolle
docker start

Die IP des Containers ermitteln

Um die IP des gestarteten Containers zu ermitteln, müssen wir uns zunächst per Shell verbinden. Dies geschieht mit dem Befehl docker exec. Bei dem von Docker bevorzugten Alpine Linux liegt die Shell auf dem Pfad /bin/sh – andere Linux nutzen z.B. /bin/bash.

docker exec -u 0 -it eloquent_haslett /bin/sh
hostname -i # IP des Containers ausgeben
exit # Verbindung wieder trennen
docker exec

Exkurs: Die IP für Windows Systeme ermitteln

Sollte der Container auf einem Windows Host laufen, dann müssen wir die IP des Containers anders ermitteln.

Dazu müssen wir in der Windows-Konsole (nicht in Unix!) den Befehl ipconfig nutzen. Die IP findet sich dann unter dem Eintrag für den Ethernet-Adapter WSL.

Windows IP config für Docker

Der erste Aufruf eines Containers über den Browser

Wir können jetzt entweder den Container über die Adresse localhost (für Windows) oder über die ermittelte IP aufrufen.

http://localhost/ bzw. http://172.24.64.1 bzw. http://172.17.0.2 (für Linux-Hosts)

Docker Tutorial Container

Als Ergebnis erhalten wir das Tutorial, das auf dem Container läuft.

Somit hätten wir erfolgreich unseren ersten Container erstellt und gestartet.

Den Inhalt eines Containers manipulieren

Das ganze Handling mit Containern wäre nur der halbe Spaß, wenn man die Container nicht auch bearbeiten, sprich: Deren Inhalte nicht verändern könnte.

Dazu werden wir jetzt die Startseite des Tutorials ein wenig verändern.

Zuerst müssen wir uns wieder mit der Shell des Containers verbinden.

docker exec -u 0 -it eloquent_haslett /bin/sh

Auf dem Container-Linux ist leider nur vi als Editor installiert. Wer damit nicht klarkommt, sollte nano installieren.

apk update
apk add nano
Alpine Linux install Nano Editor

Mit Hilfe des Befehls find finden wir heraus, wo sich die HTML-Dateien des Tutorials befinden.

find / -name index.html #  Datei(en) suchen
nano /usr/share/nginx/html/tutorial/index.html # Datei editieren
Find index.html auf Alpine Docker Container

Im Editor suchen wir jetzt mit der Tastenkombination STRG+w nach dem String „<h1>“. Die Überschrift besteht aus dem Text „Getting Started“ wir ändern ihn in „Hallo, Welt!“. Dann bitte speichern und den Editor wieder verlassen.

Rufen wir die Seite im Browser neue auf, sollte folgende Änderung zu sehen sein:

Und natürlich sollte die Änderung auch permanent sein und nicht nach Neustart verschwunden sein.

exit # um die Shell des Containers zu verlassen, falls noch nicht geschehen
docker stop eloquent_haslett # Container stoppen
docker start eloquent_haslett # Container wieder starten

Und wenn wieder die Seite im Browser aufgerufen wird, sehen wir weiterhin die Änderung.

Der umgekehrte Weg: Image aus Container erstellen

Wenn wir nun aus dem geänderten Container ein eigenes Image erstellen wollen (um es bspw. in das Repository von Docker hochzuladen oder um es Kunden zum Testen zugänglich zu machen), wird der Befehl docker commit genutzt.

docker commit <container_id> <neue_image_bezeichnung:tag>

Praktischerweise sollten wir den neuen Namen mit einem Tag versehen, um eine Versionierung zu simulieren. Für unseren Fall also Folgendes:

docker commit eloquent_haslett docker/getting_started:edited
docker images # Kontrolle
Docker Container in Image umwandeln.

Wir sehen jetzt zwei Images, das ursprüngliche, welches wir aus dem Docker Hub geladen haben und das neue mit der Hallo-Welt-Überschrift im Tutorial.