Dieses Tutorial ist VALID.

Bitte lies Dir den Disclaimer durch, bevor Du eine Anleitung umsetzt...

Haftungsausschluss / Disclaimer

phpMyAdmin Docker Container

In diesem Tutorial fügen wir erstmals alle Teile zusammen und lassen Traefik den phpMyAdmin Container ans Internet anbinden. Mit phpMyAdmin verwalten wir unsere MariaDB Datenbanken über ein bequemes Web-Interface, falls uns der Sinn mal nicht nach Kommandozeile steht.

Voraussetzungen

Für dieses Tutorial müssen die folgenden Voraussetzungen erfüllt sein:

phpMyAdmin Container Setup vorbereiten

Da wir phpMyAdmin ja von außen über das Internet als Web-Dienst aufrufen, brauchen wir einen neuen DNS-Eintrag. Außerdem legen wir ein Stammverzeichnis für phpMyAdmin und seine Konfigurationsdatei unterhalb von „/var/www“ an. An dieser Stelle waren früher alle über den Webserver freigegebenen Verzeichnisse untergebracht. Ob der guten alten Zeiten Willen führen wir diese Tradition hier fort.

DNS-Eintrag für die Subdomain „phpmyadmin“ anlegen

Wir legen einen DNS-Eintrag für unseren phpMyAdmin Container an. Dazu loggen wir uns auf der Oberfläche unseres Domain-Anbieters ein. In meinem Fall das „Customer Control Center“ von Netcup. Hier wechseln wir auf unsere Domain, die wir editieren möchten, und dort in den Reiter „DNS“. Wir erstellen eine Sub-Domain „phpmyadmin“. Für diesen Test-Server heißt die volle Domain dann „phpmyadmin.xp-server.de“. Das wird ein Domain-Eintrag, also vom Typ „A“. Noch die IP des Servers eingeben und die DNS-Einstellung anschließend abspeichern.

Nach dem Anlegen des DNS-Eintrags dauert es ein Weilchen, bis sich dieser durch die Schichten des DNS-Systems im Internet ausbreitet. Aber nach 15 bis 45 Minuten sollte der Eintrag „sichtbar“ sein. Überprüfen kann man das mit einem „Ping“ auf den Domainnamen.

Verzeichnis und docker-compose Datei erstellen

mkdir -p /var/www/phpmyadmin.xp-server.de
nano /var/www/phpmyadmin.xp-server.de/docker-compose.yml
### phpMyAdmin
### docker-compose.yml
###
##START
version: '3'
services:

 phpmyadmin:
  image: phpmyadmin/phpmyadmin
  restart: "no"
  container_name: phpmyadmin
  networks:
    - intern
    - web
  ports:
   - 80
  environment:
   PMA_HOST: maria104master
  labels:
   - "traefik.enable=true"
   - "traefik.http.routers.phpmyadmin.entrypoints=http"
   - "traefik.http.routers.phpmyadmin.rule=Host(`phpmyadmin.xp-server.de`)"
   - "traefik.http.routers.phpmyadmin.middlewares=https-redirect@file"
   - "traefik.http.routers.phpmyadmin-sec.entrypoints=https"
   - "traefik.http.routers.phpmyadmin-sec.middlewares=default-headers@file"
   - "traefik.http.routers.phpmyadmin-sec.rule=Host(`phpmyadmin.xp-server.de`)"
   - "traefik.http.routers.phpmyadmin-sec.tls=true"
   - "traefik.http.routers.phpmyadmin-sec.tls.options=myTLSOptions@file"
   - "traefik.http.routers.phpmyadmin-sec.tls.certresolver=le"
  volumes:
   - /sessions
  external_links:
   - maria104master

networks:
  intern:
    external: true
  web:
    external: true
##EOF

Ein Wort zu den Unterverzeichnissen in „/var/www“: Ich habe mir angewöhnt, diese nach ihrer URL mit dem vollen Domainnamen zu benennen. Das macht es später sehr einfach, wenn wir ein bestimmtes Verzeichnis suchen, und das genau so heißt, wie wir vermuten. Bei „blog_1“, „blog_2“ usw. wäre das deutlich schwieriger…

Gehen wir die „docker-compose“-Datei noch einmal zusammen durch:

Zeilen 5-8: Die Version (3) und der Service „phpmyadmin“ werden deklariert.

Zeile 9: Wir wählen das Image für den Container. Bei phpMyAdmin brauchen wir keine Versionsnummer angeben, es wird also immer die gerade aktuellste Version gezogen.

Zeile 10: Im Gegensatz zu den anderen Containern möchte ich diesen hier nicht immer laufen haben, sondern starte ihn manuell, wenn wir tatsächlich etwas an den Datenbanken konfigurieren. Daher die Anweisung (restart: „no“) an Docker. Nach Abschluss der Änderungen an der Datenbank fahren wir den Container auch wieder herunter. Hintergrund ist, dass wir auf dem Server keinen Dienst laufen lassen sollten, den wir nicht brauchen. Jede potentielle Schnittstelle nach draußen kann uns theoretisch auch in den Hintern beißen… Darum „so wenig wie möglich, so viel wie nötig“.
Und „Vollzugriff auf alle unsere Datenbanken“ ist garantiert nichts, das wir leichtfertig 24/7 laufen lassen sollten…

Zeile 11: Für Docker soll der Container den Namen „phpmyadmin“ bekommen.

Zeilen 12-14: Zum ersten Mal brauchen wir beide Docker-Netzwerke. Über „intern“ kommuniziert der phpMyAdmin Container mit dem MariaDB Container. Über „web“ kümmert sich unser Reverse Proxy, der Traefik Container, darum, dass eine Verbindung mit dem Internet und phpMyAdmin hergestellt wird.

Zeilen 15-16: Der phpMyAdmin Container wird mit Port 80 an Traefik gestöpselt.
Exkurs: Aber Port 80 ist ja unsicher… Was ist mit SSL? => Berechtigte Frage :)
Des Rätsels Lösung liegt in der Natur des Reverse Proxy: Nur Traefik ist nach „außen“ sichtbar und es wird aus dem Internet ausschließlich mit Traefik kommuniziert. Traefik ist auch über Port 443 erreichbar. „Hinter“ dem Reverse Proxy kommuniziert er dann ungesichert über Port 80 mit phpMyAdmin, was aber kein Problem ist, da diese Verbindung nur INTERN zwischen Traefik und phpMyAdmin, aber eben NICHT mit dem Internet abläuft. Wenn Traefik die Daten hat, gibt er sie über SSL nach außen ins Netz weiter. Traefik steht grundsätzlich immer zwischen dem Internet und allen Containern, die wir ans Netz anbinden möchten. Keiner dieser Container „spricht“ direkt mit dem Internet, sondern alle über ihren Stellvertreter, was „Proxy“ übersetzt heißt.

Zeilen 17+18: Als Environment Variable übergeben wir den Datenbank-Host an phpMyAdmin, in unserem Fall ist das der „maria104master“. Wir brauchen phpMyAdmin dann später beim ersten Start nicht konfigurieren, weil der Dienst über diese Variable den Datenbankserver schon kennt…

Zeilen 19-29: Die Label-Steuerung von Traefik. Auch hier noch einmal ein schneller Überblick:
Zeile 20: enable=true – wir wünschen, dass Traefik diesen Container ins Internet bringt.
Zeile 21: Der Entrypoint „http“ wird für den Router „phpmyadmin“ aktiviert.
Zeile 22: Dem Router „phpmyadmin“ wird der Host „phpmyadmin.xp-server.de“ zugewiesen.
Zeile 23: Wir aktivieren die Zwangsumleitung von http auf https über eine Funktion im File-Provider.
Zeile 24: Der Entrypoint „https“ wird für den Router „phpmyadmin-sec“ aktiviert.
Zeile 25: Für den Router „phpmyadmin-sec“ laden wir aus dem File-Provider die Anweisungen für die „default-headers“.
Zeile 26: Dem Router „phpmyadmin-sec“ wird der Host „phpmyadmin.xp-server.de“ zugewiesen.
Zeile 27: Für den Router „phpmyadmin-sec“ schalten wir SSL ein.
Zeile 28: Aus dem File-Provider holen wir uns zusätzliche Optionen für TLS aus dem Block „myTLSOptions“.
Zeile 29: Wir weisen Traefik an, dass er von der Zertifizierungsstelle „le“ für den Host auf dem Router „phpmyadmin-sec“ ein Zertifikat anfordert, einrichtet und dann verwaltet.

Zeilen 30+31: Die bekannten Volume-Mounts:
Der Ordner „/var/www/html“ des Containers wird persistent in einen neuen Ordner „wwwdata“ relativ zum gegenwärtigen Host-Ordner (/var/www/phpmyadmin.xp-server.de) geschrieben. „./“ heißt „relativ zum Basisverzeichnis“ in dem die „docker-compose“-Datei liegt.
Update 30.12. – Bitte streichen… Der Inhalt des Containers wird NICHT persistent abgespeichert, sonst kommen die Updates nicht vernünftig mit… Darum ist diese Zeile jetzt auskommentiert! Solltest Du die Config so übernommen haben, bitte die Zeile auskommentieren und dann das „wwwdata“-Verzeichnis löschen…

Die „/sessions“ haben keinen Mountpunkt auf dem Hostsystem (also kein Doppelpunkt). In dem Fall generiert und verwaltet die Docker-Engine automatisch ein Volume auf dem Host, welches die Daten enthält.

Zeilen 32+33: Über den „external_links“ Parameter verlinken wir den Container mit einem anderen Container. In unserem Fall ist das der MariaDB Container, dessen Service ja „maria104master“ heißt.

Zeilen 35-39: Die verwendeten Netzwerke werden noch einmal deklariert. Mit dem Parameter „external“ bitten wir docker-compose, die Netzwerke nicht zu löschen, falls der Container entfernt wird.

phpMyAdmin Container laden und starten, Logfile auswerten

Wie bei den anderen Tutorials ist das Laden und Starten des Containers schnell erledigt. Danach überprüfen wir erneut, ob der Container in Docker läuft und die Ausgabe des Logs.

docker-compose -f /var/www/phpmyadmin.xp-server.de/docker-compose.yml pull
docker-compose -f /var/www/phpmyadmin.xp-server.de/docker-compose.yml up -d
docker ps -a
docker logs -f --tail="30" phpmyadmin

Docker zeigt uns jetzt folgende drei Container:

IMAGE         COMMAND                CREATED        STATUS       PORTS                                    NAMES
phpmyadmin/..."/docker-entrypoint.…" 4 seconds ago  Up 2 seconds 0.0.0.0:32787->80/tcp                    phpmyadmin
mariadb:10.4  "docker-entrypoint.s…" 21 hours ago   Up 21 hours  127.0.0.1:3306->3306/tcp                 mariadb
traefik:2.1   "/traefik"             2 days ago     Up 2 days    0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp traefik-v2

Das Log schreibt uns recht wenig, aber mit dem Start von Apache2 läuft phpMyAdmin im Container:

AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.3. Set the 'ServerName' directive globally to suppress this message
[Sun Sep 22 10:49:00.960762 2019] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.38 (Debian) PHP/7.2.22 configured -- resuming normal operations
[Sun Sep 22 10:49:00.961085 2019] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

Einloggen ins Web-Interface

Wir starten den Browser unserer Wahl und geben in die URL-Zeile die Adresse unseres phpMyAdmin Containers ein. In meinem Fall ist das „phpmyadmin.xp-server.de“.

Beim Starten sollte uns die http => https Umleitung von Traefik direkt auf die sichere „https://“ Verbindung umschalten. Traefik macht seinen Job…
Sollte hier ein Zertifikatsfehler auftreten, war die Kommunikation mit Let’s Encrypt noch nicht fertig. Einfach 10 Sekunden warten und „Strg + F5“ drücken, bis wir das grüne Schloss sehen und die SSL-Verbindung einwandfrei klappt. Bitte NICHT weitermachen, bevor die SSL-Verbindung steht! Das MariaDB root Passwort möchten wir auf keinen Fall unverschlüsselt durchs Internet jagen!

Hat alles geklappt, werden wir von phpMyAdmin mit seinem Login Screen Willkommen geheißen:

Der Login-Screen von phpMyAdmin

Hier loggen wir uns mit dem Benutzer „root“ und dem MariaDB root Passwort ein. Ein Klick auf „OK“, und wir sollten drin sein :)

Die Oberfläche von phpMyAdmin direkt nach dem Einloggen

Herzlichen Glückwunsch :)
Das Server-Setup läuft! Wir haben über Traefik eine Verbindung ins Internet und über „intern“ eine Verbindung zur Datenbank. Der phpMyAdmin Container ist gestartet und macht, was er soll.

Mit phpMyAdmin werden Datenbankoperationen wie das Sichern oder Einspielen von Datenbanken bequem erledigt.

Container stoppen und entfernen

Wie oben in der Konfiguration bereits erwähnt ist es eine ganz schlechte Idee, diesen Dienst 24/7 auf dem Server laufen zu lassen. Im Normalfall kann nicht viel passieren, aber der Feind schläft nie und die nächste Sicherheitslücke ist direkt hinter der nächsten Ecke. Und dann möchte ich den Dienst nicht unbeaufsichtigt auf dem Server laufen haben… Denn das ist tatsächlich der „gefährlichste“ Container, den wir starten können: Vollzugriff auf alle unsere Datenbanken!

Jede weitere Anwendung, die wir in Zukunft anlegen, hat Zugriff auf ihre eigene Datenbank, aber nicht auf die der anderen Dienste. Dieses Privileg genießt ausschließlich unser phpMyAdmin Container. Darum sollten wir ihn nicht leichtfertig einsetzen, sondern nur dann, wenn wir wirklich mit dem System arbeiten müssen.

Der Container wird von docker-compose mit dem Parameter „down“ gestoppt und entfernt:

docker-compose -f /var/www/phpmyadmin.xp-server.de/docker-compose.yml down

Stopping phpmyadmin ... done
Removing phpmyadmin ... done
Network web is external, skipping
Network intern is external, skipping

Jetzt ist der phpMyAdmin Container wie erwartet aus der Liste verschwunden:

docker ps -a

IMAGE         COMMAND                CREATED        STATUS       PORTS                                    NAMES
mariadb:10.4  "docker-entrypoint.s…" 23 hours ago   Up 23 hours  127.0.0.1:3306->3306/tcp                 mariadb
traefik:2.1   "/traefik"             2 days ago     Up 2 days    0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp traefik-v2

Fazit

Die phpMyAdmin Anwendung ist in guten fünf Minuten aufgesetzt und läuft.

Jetzt sehen wir zum ersten Mal den wunderbarsten Vorteil, den dieses „dockerisierte“ Setup bietet: Wenn die Basis-Dienste „Reverse Proxy“ und „Datenbank“ eingerichtet sind, ist es ein Leichtes, Anwendungscontainer zu starten, die dann „automatisch“ nach außen angebunden und mit SSL-Zertifikaten versorgt werden.

Die Geschwindigkeit, mit der wir diese Dienste bereitstellen können, ist atemberaubend! Außerdem behalten wir zu jeder Zeit den Überblick und die volle Kontrolle, welche Container laufen und welche wir stoppen.

Es ist ein so schönes Gefühl, wenn der Server wie eine gut geölte Maschine schnurrt und all die kleinen Zahnrädchen perfekt und in Harmonie ineinandergreifen…

Referenz Links

Anzeige *

11 Kommentare zu „phpMyAdmin Docker Container“

  1. Hallo Peter
    zuerst mal wünsche ich Dir ein gutes, gesundes und Erfolgreiches neues Jahr und herzlichen Dank für Deine Hilfe.
    Betreffend mariadb habe ich eine Frage, ob und wie das einbinden eines Containers mit anderer IP (Proxmox) möglich ist. Kann statt environment PMA_Host: einfach eine IP-Adresse eingegeben werden? Sorry, aber ich finde nirgends wie ich das anstellen könnte, denn ich würde gerne einen Haupt-Container Traefik (IP 192.168.1.131) und dann darin auf weitere IP’s mit z.B. der Adresse 192.168.1.133, 192.168.1.134 etc zugreifen.
    Ist dies überhaupt möglich?
    Gruss Jakob

    1. Hallo Jakob,
      tut mir leid, aber ich steh gerade richtig auf dem Schlauch, was Du genau machen willst…

      Die Container bekommen von Docker eine private Klasse-B IP zugewiesen. Welche das ist, kannst Du mittels „docker network inspect intern“ zum Beispeil für das Netz „intern“ herausfinden.
      Containerweise werden die untereinander über ihre Namen verbunden, weil die IPs der Container sich beim Starten und Stoppen jederzeit ändern können. Da müsstest Du jedes Mal nachschauen und dann händisch sämtliche docker-compose-Dateien anpassen.

      Ich wüsste jetzt nicht, wie Du den Containern private Klasse-C IP Adressen zuweisen kannst. Oder warum Du das überhaupt möchtest.
      Wenn dem Container ein Docker-Netzwerk mitgegeben wird, kann der darüber mit den anderen Containern, die ebenfalls in diesem Netzwerk liegen, kommunizieren. Darüberhinaus ist es möglich, die Container an die Host-IP anzubinden (was wir mit dem mariaDB-Container auch machen).

      Liebe Grüße
      Peter.

      1. Hallo Peter,
        danke für die Info. Ich stand da irgendwie auf dem Schlauch. Jetzt habe ich soweit verstanden, dass ich die mit dem Befehl docker network inspect intern von mariadb die IPv4Adresse 172.22.0.2/16 des containers finde, welche im Subnet 172.22.0.0/16 liegt mit dem Gateway 172.22.0.1.
        Der andere Container mit Traefik hat 172.16.00/16 mit gateway 172.16.01. Diesen Container wollte ich mit dem mariadb container verbinden, was ja anscheinend nicht geht.
        Da muss ich wohl etwas anderes als proxmox nehmen und statt dessen einen Debian-Server aufsetzen.
        Danke nochmals für Deine Geduld
        Gruss Jakob

        1. Der Traefik-Container hat nur das „Web“-Netzwerk von Docker.
          mariaDB hat nur das „Intern“ Netzwerk von Docker.
          Aus dem Grund können die nicht untereinander verbinden. Traefik braucht auch keine Datenbank. Und die Datenbank braucht keinen Internetzugang.

          Wenn ein anderer Container Zugriff auf maria UND Traefik haben will (wie phpMyAdmin), dann bekommt der beide Netzwerke eingetragen.
          Wer dann mit wem über welches Netz „redet“, regelt Docker.

  2. Hallo Peter,
    ich habe ein Problem mit derm Netzwerk:
    /phpmyadmin/docker-compose.yml‘ is invalid because:
    Unsupported config option for services.networks: ‚intern‘
    Ich habe alles gemäss Deinen Anleitungen installiert und probiert, den Fehler zu finden.
    Leider komme ich nicht dahinter.
    Schöne Grüsse
    Jakob

    1. Hallo Jakob,
      hmm… Aus der Ferne kann ich da jetzt wenig dazu sagen.
      Debian 10 hast auch genau so installiert wie im Basis-System-Tutorial?

      Wo genau tritt der Fehler auf – also bei welchem Befehl?
      Und dann bräuchte ich Deine phpmyadmin docker-compose.yml und die von Traefik auf fiedler@cpf.de
      Ich schau mal kurz drüber.

      Beste Grüße
      Peter.

      1. Hallo Peter
        jetzt klappt es plötzlich. Habe alles neu aufgesetzt und genau nach Deinen Anweisungen erstellt. Somit läuft es nun. Danke
        Gruss und bleib gesund
        Jakob

  3. Norbert Schmidt

    Ich habe 2 Fragen:
    1. Gibt es vielleicht eine Möglichkeit die phpMyAdmin oder auch Matomo Seiten über Unterverzeichnisse der Art: https://www.mydomain.de/phpMyAdmin in Traefik erreichbar zu machen?
    2. Kann ich Traefik so einrichten, dass es nicht per Let’s Encrypt ein Zertifikat erstellt sondern ein vorhandenes Wildcard Zertifikat verwendet?

    Schöne Grüße
    Norbert Schmidt

    1. Hallo Norbert,

      SubFOLDER anstelle von SubDOMAINS gehen. Die bekommt man nur nicht vernünftig mit Let’s Encrypt zertifiziert. Aber da das bei Dir ja keine Rolle spielt… Hier wäre eine Anleitung, wie man die Subfolder definiert:
      https://medium.com/@iced_burn/reverse-proxy-in-traefik-with-subdirectories-eef4261939e

      Zu Frage 2: Ja, das geht auch. Beschrieben ist der Vorgang hier:
      https://doc.traefik.io/traefik/https/tls/

      Leider hab ich weder das eine, noch das andere je probiert und kann Dir darum bei der Implementierung nicht helfen.
      Viel Glück und beste Grüße
      Peter.

Kommentar verfassen

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

Verwendung
von Cookies

Um unsere Webseite für Sie optimal zu gestalten und fortlaufend verbessern zu können, verwenden wir Cookies. Durch die weitere Nutzung der Webseite stimmen Sie der Verwendung von Cookies zu. Weitere Informationen zu Cookies erhalten Sie in unserer Datenschutzerklärung.

Scroll to Top