Docker

Ekkart Kleinod  • 

Docker ist ein mächtiges Werkzeug, um plattformübergreifend und ohne Installation von Servern etc. diese laufen zu lassen. Es bedient sich dabei ganz ok, dennoch: die Lernkurzve ist sinusförmig

Installation

Docker installieren

Docker-CE nehmen, Installationsanleitung:

Den GPG-Key installieren und den Fingerprint 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 verifizieren:

$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
pub   4096R/0EBFCD88 2017-02-22
      Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid   Docker Release (CE deb) <docker@docker.com>
sub   4096R/F273FCD8 2017-02-22

Dann die deb-Zeile für die Paketverwaltung herauskriegen:

$ echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Unter LinuxMint noch mal schauen, ob $(lsb_release -cs) den richtigen Wert geliefert hat.

Das Ergebnis in die Paketverwaltung eintragen und installieren:

  • docker-ce
  • docker-ce-cli
  • containerd.io

Docker-Compose installieren

Binary runterladen, ablegen und ausführbar machen:

Zunächst herusfinden, welche die aktuelle Version von docker-compose ist:

Die Versionsnummer dann hier ergänzen:

$ sudo curl -L https://github.com/docker/compose/releases/download/<version>/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

Die Code-Completion aus Faulheit gleich noch dazu:

$ sudo curl -L https://raw.githubusercontent.com/docker/compose/<version>/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose

Testen

$ docker-compose --version
docker-compose version 1.17.1, build 6d101fb

Docker-Gruppe

Wenn die aktuelle Nutzerin nicht in der docker-Gruppe ist, muss docker immer als root gestartet werden: unbequem, Sicherheitsrisiko und Problem mit Dateizugriffsrechten.

Gruppen auflisten, nach docker filtern und Gruppen anzeigen, zu denen die aktuelle Nutzerin gehört:

$ cat /etc/group
$ cat /etc/group | grep docker
$ groups $USER
$ cat /etc/group | grep $USER

Gruppe anlegen (wenn sie nicht existiert) und Nutzerin hinzufügen:

$ sudo groupadd docker
$ sudo usermod --append --groups docker $USER

Jetzt am besten neu starten, damit Code Completion und Gruppenzugehörigkeit übernommen werden. It's the only way to be sure.

Wordpress-Entwicklung mit Docker

Statt die Produktivumgebung zu zerstören, kann man prima ein Plugin mit Docker entwickeln, testen und dann ausliefern.

  1. Docker-Compose-Konfigurationsdatei erstellen
  2. Container mit docker-compose starten
  3. Container mit docker-compose stoppen

Die Schritte 4 und 5 dann immer, wenn entwickelt werden soll.

Docker-Compose-Konfigurationsdatei erstellen

Einstellungen für die Seite. Eigentlich fast direkt aus Doku kopiert:

Dateiname: docker-compose.yml

Hier sind die Entwicklungsdateien korrekt einzubinden. Dafür wird bei volumes ein Mapping angelegt vom Dateisystem in das Docker-Dateisystem.

Im Beispiel liegen die Entwicklungsdateien des Plugins postpone-posts im Verzeichnis ../postpone-posts/ relativ zur Konfigurationsdatei. Dieses Verzeichnis wird von Docker für Wordpress in das Verzeichnis /var/www/html/wp-content/plugins/postpone-posts gemappt.

Zusätzlich binde ich noch phpmyadmin ein, um die Änderungen an der Datanbank nachverfolgen zu können.

version: '3'

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
    volumes:
      - "../postpone-posts/:/var/www/html/wp-content/plugins/postpone-posts"

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin
    environment:
      PMA_ARBITRARY: 1
      PMA_HOST: db
      PMA_PORT: 3306
      PMA_USER: wordpress
      PMA_PASSWORD: wordpress
    restart: always
    ports:
      - 8080:80
    volumes:
      - /sessions

volumes:
  db_data:

Docker starten

Der Start erfolgt über Docker-Compose, beim ersten Start werden alle benötigten Dateien heruntergeladen.

$ sudo docker-compose up -d

Die Wordpress-Installation ist danach verfügbar unter

phpmyadmin ist erreichbar unter

Docker stoppen

Auch das Stoppen erledigt Docker-Compose.

$ sudo docker-compose down

Wordpress-Debugging

Für den Test eines Plugins muss man die debug-Variable WP_DEBUG auf true setzen. Dies geschieht über die Datei wp_config.php, die im Root-Verzeichnis der Wordpress-Installation liegt.

Diese Datei muss man aus dem Container extrahieren und dann einbinden oder in den Container zurückkopieren, wie man möchte.

Dazu findet man zuerst die ID oder den Namen des Containers heraus:

$ sudo docker container ls
CONTAINER ID   IMAGE                   ...  NAMES
032d18e6d816   wordpress:latest             dev_wordpress_1
56aabe83c2f2   mysql:5.7                    dev_db_1
49d804195636   phpmyadmin/phpmyadmin        phpmyadmin

Wordpress ist also unter der ID 032d18e6d816 oder dem Namen dev_wordpress_1 ansprechbar. Wir kopieren die Datei in das lokale Verzeichnis:

$ sudo docker cp dev_wordpress_1:/var/www/html/wp-config.php .

Jetzt können wir die Datei editieren und dann zurückspielen.

Ich bevorzuge das Zurückkopieren in den Container nach jeder Änderung, damit Änderungen durch das System erfasst werden (die theoretisch nicht auftreten sollten, aber...)

$ sudo docker cp wp-config.php dev_wordpress_1:/var/www/html/

Dabei muss man "nur" daran denken, vor jeder Änderung wieder eine Kopie aus dem Container zu holen und diese zu modifizieren.

Will man testen, ob der debug-Modus eingeschaltet ist, hilft folgender Code:

if (defined('WP_DEBUG') && true === WP_DEBUG) {
  echo '<p>Debug mode</p>';
}

Docker-Netzwerk / Zugriff zwischen Containern

Ausgangslage

  • zwei Docker-Container
    • Apache auf Port 8080
    • Python

Problem

Lösung

  • Docker-Container, die aufeinander zugreifen sollen, müssen im selben Netzwerk laufen
  • docker selbst über explizites Erstellen und Nutzen eines Netzwerks
  • im Python-Container erfolgt der Zugriff dann über http://myserver:80/
$ sudo docker network create mynetwork
$ sudo docker run --publish 8080:80 --network mynetwork --rm --name myserver httpd:alpine &
...
$ sudo docker run --rm --interactive --tty --network mynetwork --volume "${PWD}":/usr/src/myapp --workdir /usr/src/myapp python:rc-alpin script.py
...
$ sudo docker container stop myserver
$ sudo docker network rm mynetwork
  • in docker-compose kann das Netzwerk über networks: erstellt und genutzt werden

Shell/bash in Container starten

Container normal starten, via docker oder docker-compose, dann:

$ docker exec --interactive --tty <container_name> bash