Kolumne: Olis bunte Welt der IT

Heute schon gedockert? Was Docker im Alltag alles kann
Keine Kommentare

Docker ist ein Schweizer Taschenmesser in der IT, nicht nur eine Technologie für komplexe Systemumgebungen und Cloud-Deployments. Das Tolle an Docker ist, dass es so einfach einzusetzen ist. Schauen Sie sich Docker einmal im Detail an!

Ich habe bestimmt schon einmal erwähnt, dass ich gern VMware benutze. Die Plattform begleitet mich jetzt seit den späten 90er Jahren. Damals entwickelte meine Firma Geschäftsanwendungen für mehrere Kunden, und es stellte sich als der beste Weg heraus, die unterschiedlichen Entwicklungsumgebungen für die Kundenprojekte mit Hilfe virtueller Systeme strikt zu trennen. Natürlich ließen sie sich dadurch gleichzeitig auch archivieren und versionieren, was im Lauf der Zeit durch drastisches Wachstum der Massenspeicher immer einfacher wurde. Ich bin immer wieder darüber erstaunt, dass sich Entwickler auch heute noch über dieselben Probleme beklagen, die ich durch den Einsatz virtueller Maschinen seit zwanzig Jahren nicht mehr habe.

Alltagstauglich? Docker vs. VMware

Um virtuelle Maschinen im „alten“ Sinne soll es hier allerdings nicht gehen. Seit längerer Zeit spielt eine andere Technologie eine wichtige Rolle in meinem Alltag: Docker. Nun haben Sie zu Docker sicherlich schon viel gehört und gelesen, denn es ist ja keine Neuheit mehr. Allerdings habe ich in Gesprächen festgestellt, dass für viele Entwickler die Einschätzung dazu, was man mit Docker machen kann, offenbar anders ist als meine. Natürlich ist Docker komplex – man kann an aufwendige Deployment-Szenarien denken, mit Schwärmen, Clustern, Kubernetes und anderen Fachbegriffen, die eigentlich nur IT-Leuten so richtig etwas sagen (oder auch nicht). Ich habe solch komplexe Projekte miterlebt, aber der Umgang mit dieser administrativen Seite der Technologie zählt für mich (zum Glück) nicht zum Alltagsgeschäft.

Docker ist einfach

Das Tolle an Docker ist, dass es so einfach einzusetzen ist. Für den Anfang ist da die Ad-hoc-Verwendung eines Servers oder Dienstes, vermutlich aus der Open-Source-Ecke, der für eine Testumgebung gerade benötigt wird. Zum Beispiel gibt es eine Kundenanfrage mit einem Testprojekt, das MySQL verwendet. Wenn ich früher MySQL brauchte, musste ich es erst installieren. Auf meinem Linux-System ist das mit apt-get install mysql wahrscheinlich erledigt, aber etwa unter Windows sind grafische Installer leider noch immer sehr verbreitet. Am Rande: Ich empfehle sehr die Verwendung von Chocolatey, damit installiert man MySQL ebenfalls mit einem einzigen Kommando. Nun geht’s mit dem Problem aber weiter – aller Wahrscheinlichkeit nach habe ich MySQL sowieso auf dem Rechner, aber es ist eben auch schon für andere Zwecke vorkonfiguriert. Da gibt es bestehende Datenbanken von anderen Projekten, Datenbanken für Systemsoftware, die ebenfalls MySQL verwendet, Benutzeraccounts mit Berechtigungen usw. Um das besagte Testprojekt des Kunden „mal eben“ zu starten, ist sorgfältige Vorbereitung gefragt, damit nicht etwas anderes dabei kaputt geht.

BASTA! 2020

Entity Framework Core 5.0: Das ist neu

mit Dr. Holger Schwichtenberg (www.IT-Visions.de/5Minds IT-Solutions)

Memory Ownership in C# und Rust

mit Rainer Stropek (timecockpit.com)

Softwarearchitektur nach COVID-19

mit Oliver Sturm (DevExpress)

Mit Docker MySQL zu starten ist ganz einfach: docker run -p 3306:3306 mysql:latest ist ein guter Anfang. Der Name mysql lässt sich im Docker Hub finden, und latest ist ein Tag, das beim Download (meistens) die neueste Version selektiert. Für penible Leser sei gesagt, dass die Tags beliebig gesetzt werden können, also könnte latest auch etwas anderes als die letzte Version bezeichnen – die Seite für das Image im Docker Hub zeigt die verfügbaren Tags und Versionen. Wenn Docker die angegebene Image-Version schon lokal findet, schaut es von selbst nicht nach Updates, daher sollten Sie der Sicherheit halber hin und wieder docker pull mysql:latest ausführen. Generell, und besonders beim ersten Versuch, ist der Vorgang allerdings ganz automatisch.

Images und Container

Ein paar Worte zur Terminologie. Das Image ist das, was im Beispiel vom Docker Hub geladen wird. Images haben mehrere Layer, also Schichten, sodass der Download einer neuen Version oft nicht sehr lange dauert, wenn manche Schichten sich gegenüber der alten Version nicht geändert haben. Wenn Sie ein Image „starten“, wird ein Container auf Basis des Images erzeugt. Der Container enthält die Laufzeitumgebung, darin können auch Daten von laufenden Prozessen abgelegt werden. Den Container können Sie behalten, beenden und später wieder starten, oder manuell oder automatisch nach dem Lauf wieder entfernen. Das Image hingegen ändert sich nie.

Mit dem Parameter -p Ziel:Quelle wird ein Port aus dem Container für den Hostrechner verfügbar gemacht. -p 3306:3306 macht also den Standardport von MySQL lokal verfügbar, als ob MySQL direkt auf dem Hostsystem liefe. Wenn Sie ein lokales MySQL bereits auf Port 3306 laufen haben, könnten Sie mit -p 3307:3306 einfach einen anderen Hostport verwenden.

Zum Ausprobieren

Wenn Sie nun den Befehl oben ausprobieren, werden Sie feststellen, dass noch etwas fehlt. Mit anderen Docker Images könnte nun durchaus schon alles laufen, aber MySQL möchte noch ein paar Parameter übergeben bekommen, damit es sich ordentlich initialisieren kann. Solche Parameter werden oft in Form von Environment-Variablen übergeben. Zum Ausprobieren empfehle ich also dies:

docker run --rm -it -p 3306:3306 -e MYSQL_ROOT_PASSWORD=superSecret -e MYSQL_DATABASE=testdb mysql:latest

Die beiden übergebenen Variablen werden von MySQL verwendet, um ein Passwort für den Benutzer root zu setzen und eine erste Datenbank zu erzeugen. Der Parameter -it wird oft verwendet, um den Hauptprozess des Containers im Terminal ansprechbar zu machen, zum Beispiel, wenn Sie dort etwas eintippen wollen. Je nach Prozess ist das nicht unbedingt notwendig, schadet aber auch nicht – das Gegenteil ist -d, mit dem Sie den Container im Hintergrund laufen lassen. Schließlich ist –rm für die gelegentliche Arbeit mit einem Image sehr praktisch, denn es löscht nach erfolgtem Ablauf den Container automatisch wieder.

Oft ist es so, dass sich ein Container, der im Vordergrund läuft, durch CTRL + C abbrechen lässt. Dies hängt allerdings vom Prozess selbst ab, und MySQL reagiert auf CTRL + C (also das Signal SIGINT) nicht. Stattdessen können Sie CTRL + \ (Backslash) benutzen, was ein SIGQUIT sendet. Wenn sich allerdings ein interaktiver Container mal gar nicht beenden lässt, oder um einen Hintergrundcontainer zu beenden, müssen Sie ein separates Kommando verwenden. Mit docker ps finden Sie heraus, welche Container gerade laufen:

> docker ps  
CONTAINER ID IMAGE        COMMAND ...
ad37a661b806 mysql:latest "docker-entrypoint.s…" ...

Mit docker stop <id> beenden Sie einen Container. Dabei müssen Sie die ID nicht vollständig eingeben – nur eindeutig muss sie sein. Im Beispiel wäre also docker stop ad37 ausreichend. Es ist auch möglich, dem Container beim Start mit –name <name> einen Namen zu geben, der später zum Beenden verwendet werden kann.

Die letzte wichtige Grundlage ist der Umgang mit den Verwaltungswerkzeugen. Mit docker container ls und docker image ls lassen Sie sich anzeigen, welche persistenten Container und Images auf dem System liegen. Docker container prune löscht alle nicht laufenden Container – Ähnliches gibt es auch für Images. Mit docker –help bzw. docker container –help und anderen bekommen Sie Hilfestellung zu den verfügbaren Parametern. Es empfiehlt sich, gelegentlich etwas aufzuräumen, da große Zahlen von Images und alten Containern eventuell viel Speicher verbrauchen.

Docker als Schweizer Taschenmesser

Nun lassen sich mit Docker verschiedene Alltagsprobleme ganz einfach lösen. Zum Beispiel hatte ich einmal ein paar Skripte geschrieben, mit deren Hilfe ich Blogposts formatieren konnte. Ich hatte die Artikel in Markdown geschrieben, was der Blog allerdings nicht verstand. Also hatte ich in typischer Linux-Art ein Makefile gebaut, das mit ein paar sed-Kommandos und einem Aufruf an das Node-basierte Marked den Artikel mit ordentlich eingebauten High-DPI-Bildern nach HTML konvertierte und das Format von Codeblöcken so anpasste, dass sie im Blog korrekt formatiert waren. Irgendwann gab es dann Nachfragen nach vorformatierten Codeblöcken und ich erweiterte mein System mit einem Perl-Skript zum Parsen und der Abhängigkeit vom Python-basierten Pygments für das Format. Das funktionierte alles prima, war aber leider etwas abhängig von meiner Systemumgebung. Als nun ein paar Kollegen mein Skript auch gern benutzen wollten, und zwar möglichst unter Windows, musste ich eine Lösung finden.

Die Lösung: Docker! Damit kann ein Image vorbereitet werden, das meine Systemumgebung abdeckt. Nebenbei wird so diese Umgebung auch standardisiert und dokumentiert, in Form der Konfigurationsdatei für das Image. Um ein eigenes Docker Image zu bauen, erzeugen Sie eine Datei namens Dockerfile. Listing 1 zeigt die Datei für mein Beispiel.

FROM node:latest

RUN npm install -g marked

RUN apt-get update && apt-get install -y python3-pip libipc-run-perl
RUN pip3 install pygments
RUN pip3 install jsx-lexer

RUN mkdir -p /usr/src/convertmd
COPY makefile.convertmd /usr/src/convertmd
COPY make.sh /usr/src/convertmd
COPY md-replace-image /usr/src/convertmd
COPY codeblocks.pl /usr/src/convertmd
COPY custom_html.py /usr/src/convertmd
COPY blogsdark.py /usr/local/lib/python3.5/dist-packages/pygments/styles
COPY blogslight.py /usr/local/lib/python3.5/dist-packages/pygments/styles

WORKDIR /usr/src/convertmd/md-replace-image
RUN npm install
RUN npm link

RUN mkdir /work

CMD [ "/usr/src/convertmd/make.sh" ]

In der Datei gibt FROM an, welches vorhandene Image die Basis des neuen bildet. Node enthält natürlich bereits eine typische Node-Umgebung, sodass mit einer RUN-Anweisung npm ausgeführt werden kann, um Marked zu installieren. Mit anderen, ähnlichen Tools installiere ich dann notwendige Systemwerkzeuge sowie die Python-Komponenten. Mit COPY werden Dateien vom Host in das Image übertragen. Wichtig: All die Kommandos im Dockerfile laufen während des Build-Vorgangs ab. Dieser muss nun gestartet werden, im Beispiel so:

docker build -t oliversturm/convertmd -f Dockerfile .

Docker build akzeptiert einen Parameter -t, mit dem ein Tag für das Image erzeugt wird. Der Befehl endet in einem Punkt, da er sich auf das lokale Verzeichnis bezieht. Nach dem Build kann ich das Image im Docker Hub für andere verfügbar machen. Mit docker login gebe ich dazu meine Accountdetails an, und docker push oliversturm/convertmd:latest lädt mein Image hoch. Zur Verwendung des Image auf einem anderen Computer dient nun dieses Kommando:

docker run -v <lokaler Ordner>:/work oliversturm/convertmd:latest

Geht auch unter Windows

Der Parameter -v ist neu: damit wird ein Hostverzeichnis im laufenden Container verfügbar gemacht, im Pfad /work. Unter Windows könnte der Befehl zum Beispiel wie folgt aussehen, um im aktuellen Verzeichnis zu arbeiten: docker run -v %cd%:/work oliversturm/convertmd:latest. Mit diesem einen Befehl, den man natürlich auch in eine Batch-Datei legen kann, lässt sich nun auf einer Windows-Maschine der gesamte automatisierte Skriptprozess mit all seinen Komponenten aus Linux, JavaScript, Perl und Python ausführen.

Als weiteres Beispiel sei abschließend eins genannt, das als zusätzliches Werkzeug Docker Compose einsetzt. Neulich wurde ich gebeten, an einem Theme für WordPress zu arbeiten. Diese Themes sind in PHP geschrieben, enthalten aber auch viele HTML- und JavaScript-Inhalte. Um sie ordentlich testen zu können, braucht man WordPress und PHP, einen Webserver und einen Datenbankserver. Dann muss das Theme in WordPress installiert werden, bevor man es testen kann. Oder aber … man verwendet Docker.

Ich erzeugte für diesen Fall eine Konfigurationsdatei für Docker Compose. Dieses Tool kann ein Gesamtsystem aus mehreren Docker-Containern starten und verwalten. Es ist aber im Einsatz so einfach, dass es auch für diesen Zweck verwendbar ist. In Listing 2 sehen Sie den Inhalt der Datei docker-compose.yml:

version: '3.3'

services:
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - ./theme:/var/www/html/wp-content/themes/testtheme
    ports:
      - '80:80'
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: my_wordpress_db_password

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: my_db_root_password
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: my_wordpress_db_password

Zum großen Teil stammt dieses Set-up aus der Dokumentation von WordPress, wo dessen Einsatz mit docker-compose beschrieben wird. Allerdings erkennen Sie die Bestandteile wieder, denn die meisten Elemente habe ich schon oben für Docker selbst beschrieben. Neu ist, dass Docker Compose Abhängigkeiten versteht, so wird im Abschnitt depends_on der MySQL-Container für WordPress eingetragen. Der Dienst db ist damit für den Dienst wordpress auch als Netzwerksystem ansprechbar, wie in der Umgebungsvariable WORDPRESS_DB_HOST zu sehen ist. Im Abschnitt volumes wird, ähnlich wie in meinem vorherigen Beispiel, ein lokales Verzeichnis (in dem liegt das WordPress Theme) im Container verfügbar gemacht – so ist das Theme direkt für WordPress verfügbar und kann dort ohne zusätzliche Installation aktiviert werden.

Automatisch beide Container verbinden

Mit docker-compose up -d starten automatisch beide Container und werden miteinander verbunden. Auf Port 80 des Hosts läuft nun WordPress! Als letzte Feinheit möchte ich jetzt noch die Theme-Dateien überwachen lassen und automatisch im Browser neu laden, wenn sie sich ändern. Das lässt sich mit dem JavaScript-Tool Browsersync erreichen und einer kurzen Konfiguration in der Datei bs-config.js (Listing 3).

module.exports = {
  ui: {
    port: 3001
  },
  files: [
    './theme/**/*.css',
    './theme/**/*.php',
    './theme/**/*.js'
  ],
  watchEvents: ['change'],
  watch: trü,
  proxy: 'http://localhost/',
  port: 3000
}

Nun starte ich browser-sync start –config bs-config.js und alles funktioniert – Browsersync überwacht die konfigurierten Dateien und fungiert als Proxy, indem es die WordPress-Seite von http://localhost lädt und über Port 3000 wieder verfügbar macht. Nun kann ich in VS Code an dem Theme arbeiten, und wenn ich Änderungen speichere, werden diese automatisch im Browser angezeigt, in der vollständigen WordPress-Umgebung.

Fazit

Ich hoffe, dass ich Interesse an Docker geweckt habe, wo vielleicht noch keins war. Womöglich haben meine Beispiele Ihnen auch Ideen gegeben. Aus meiner Sicht ist Docker ein Alltagswerkzeug mit vielfältigen Anwendungsbereichen, nicht nur eine Technologie für komplexe Systemumgebungen und Cloud-Deployments. Schauen Sie sich Docker einmal im Detail an!

Windows Developer

Windows DeveloperDieser Artikel ist im Windows Developer erschienen. Windows Developer informiert umfassend und herstellerneutral über neue Trends und Möglichkeiten der Software- und Systementwicklung rund um Microsoft-Technologien.

Natürlich können Sie den Windows Developer über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. Außerdem ist der Windows Developer weiterhin als Print-Magazin im Abonnement erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -