Infos aus dem 6-teiligen Heise-Tutorial
Erstellung eines Volums.
Volums sind dafür da, um eigene Daten aufzunehmen. Damit diese nicht direkt in einen Container erfasst werden, legt man unter /usr/share zum jeweiligen Programm, z.B. nginx, ein Volume an.
Die Syntax wäre in diesem Beispiel wie folgt:
some-nginx = Name des Containers
-v = ein Volume anhängen und deklarieren
-d = Dienst läuft im Hintergrund
nginx = Image
ro = read only
Hinweis:
In einem Dockercontainer sind nur die wichtigsten Pakete enthalten. Will man eine Textdatei erstellen, aber ein Editor ist nicht verfügbar, kann man pragmatisch folgendes machen:
Damit erstellt man eine Datei, die dann verwendet werden kann. Will man künftig mehr in dem Container machen, empfiehlt es sich, einen Editor zu installieren (und daraus dann ein eigenes Build zu machen). Das wird so aber nicht empfohlen (?). Insgesamt ist das der denkbar schlechteste Weg.
Fazit:
Mit docker exec in einen Container zu gehen und dort Daten zu bearbeiten ist nicht gut und sollte so nicht gemacht werden.
Die Anwendungsdaten werden im Container nicht gespeichert. Sobald der Container beendet wird, sind die Daten weg. Daher müssen Volumes angelegt werden, die die Anwendungsdaten speichern udn vorhalten.
Um ein Volume zu erzeugen, ist folgender Befehl notwendig:
Dieser Befehl erzeugt einen langen Name aus Zufallszahlen/-ziffern. Man kann den Volumennamen auch vorgeben:
Mit dem ls-Befehl kann ich mir die vorhandenen Volumes anzeigen lassen:
Das läuft analog zu den Images und den Containern.
Um nun das erzeugte Volume mit dem Namen html in den nginx-Container zu bringen, wird eine zweite Instanz aufgemacht und ein weiterer Port eröffnet (nicht zwingend erforderlich, nur zur Demonstration):
ro heißt readonly.
Das erzeugte Volume liegt hier:
Dieses Verzeichnis kann ein Normaluser, selbst wenn er in der Gruppe docker ist, nicht sehen (sudo -s)
WICHTIG:
Selbst wenn der Container zerstört wird, bleibt das Volume erhalten. Wichtig ist dann dabei, dass das Verzeichnis /usr/lib/docker gesichert wird, wenn in diesem Verzeichnis Nutzer- und Anwendungsdaten für die weitere Verarbeitung gespeichert werden, also produktiv genutzt werden.
Die Volumes müssen nicht unbedingt im Docker-Verzeichnis liegen, sondern können an jeder beliebigen Stelle gespeichert werden. Dazu wäre dann z.B. dem Volume HTML das Verzeichnis voranzustellen (Beispiel): /home/django/dockervolume/HTML
Die Prozesse, die innerhalb der Container laufen, müssen allerdings die Berechtigungen auf dieses Verzeichnis haben.
Docker und Netzwerke
Docker erzeugt ein eigenes Netzwerk: docker0
Docker hat verschiedene Netzwerke, die man sich so anzeigen lassen kann:
Beispiel, wie zwei Container kommunizieren.
Ein Blogsystem auf Basis WordPress-Blogsystem
Container für Datenbank:
Container für WordPress / Webserver
Hinweis:
Dieser Part "test-mysql:test-mysql" bedeutet, dass der Container test-mysql auch als test-mysql angesprochen werden. Soll dieser Name dann anders lauten, müsste er angegeben werden (z.B. test-mysql:test-worpress).
Hinweis:
Docker hat einen eigenen DNS-Server laufen.
Für das obige Beispiel würde im Browser, da wir mit WordPress arbeiten wollen, folgendes einzugebenn sein:
Sodann würde die Installation von WordPress erfolgen.
Die Daten von WordPress werden in der Datenbank abgespeichert. WordPress und die Datenbank sind in zwei Containern aufgeteilt. Um mit den eingegebenen Daten weiter arbeiten zu können, müssten die Daten in ein Volume übertragen werden
Wie das geht, weiß ich noch nicht!
Wenn z.B. WordPress vom Rest der Welt trennen möchte, dann kann das über ein eigenes Docker-Netzwerk erfolgen. Das sieht dann so aus:
Prüfen, ob das Netzwerk angelegt ist bzw. welche vorhanden sind, kann man mit:
Dieses neue Network kann man an den Run-Befehl für mysql hängen:
Hinweis:
Es gibt den inspect-Befehl. Dieser kann auf das Netzwerk angewandt werden. Um das neue Netzwerk zu inspizieren, ist folgendes notwendig:
Man kann also in das Netzwerk "hineinschauen".
Wie kann man Docker vereinfachen?
Contaner mit Compose einrichten
Mehrere Container nebeneinander betreiben.
Docker-Compose ist ein Python-Script (offizell von Docke unterstützt), mit dem vereinfacht mehrere Container aufgebaut und miteinander verbunden werden können.
Ein Compose-File ist wie folgt strukturiert (Beispiel MySQL-Container)
Die Inhalte sind quasi die gleichen wie in einem run-Befehl.
Die Aussage ist, dass selbst, wenn nur ein Container laufen soll, eine Compose-File nützlich ist.
Der data-Ordner des Volume liegt in dem Ordner, aus dem das Compose-File aufgerufen wird. Der Punkt weist auf die relative Lage hin. Hat mein einen eigenen Bereich auf der lokalen Festplatte eingerichtet, ruft man das File eben von dort aus auf.
Für das Beispiel aus dem Netzwerkabschnitt (WordPress und MySQL) sieht das Compose-File wie folgt aus:
So wird die yml-Datei, in der das Compose-File abgespeichert wurde, ausgeführt:
Damit wird wohl alles an Compose-Files gestartet.
Die Ausführung dieses Befehl ist sichtbar, da die Option -d nicht mit angegeben worden ist.
Ansonsten könnte man bei der Sichtbarkeit die einzelnen Aktionen sehen, die ausgeführt würde. Es gibt dann wohl, sobald der Datanbankserver oben ist mit der Installation von Wordpress im Browser.
Hinweis:
In einer yml-Datei ist die Einrückungstiefe immer 2 Leerzeichen. Man kann auch Tabs verwenden, aber zwei Leerzeichen sind wohl Standard.
Um z.B. auf der Shell in die Container mit dem exec-Befehl einzusteigen, kann folgender Befehl genutzt werden:
Damit ist man im Container anstelle des komplexen Befehlaufrufes aus den Anfängen.
Die grafische Oberfläche für Docker
Portainer ist eine bekannte grafische Oberfläche
Sofern im Compose-File der Portainer integriert ist, kann man in der Adressezeile des Browsers über den Port 9000 die Webseite erreichen.
Ich unterstelle derweil, dass das möglich ist, denn in dem Beispiel bei Heise wird mittlerweile eine echte Domain genutzt. Sollte aber auch mit localhost funktionieren.
Zertifikate erstellen
Die Anwendungen, die man in Docker erstellt, kann man sind Internet bringen. Man muss dafür aber vieles beachten, um die Sicherheit zu gewährleisten. Mit Zertifikaten kann man das erreichen.
Eine Grundlage ist z.B. Watchtower (wird niht mehr entwickelt, es gibt was neues) und gehört zu vorherigen Compose-File.
Watchtower ein Image, welches sich um die Aktualisierung von Images kümmert, was durch Docker selber nicht geleistet wird.
Um von außen auf die Anwendung schauen zu können, wird folgendes benötigt (Revers-Server/Proxy oder so ähnlich)
Für das nachfolgende Beispiel muss der WordPress-Container angepasst werden, da diese keine Ports mehr freigeben darf (wird weiter unten mit 80 und 443 gemacht):
Ob das auch auf localhost läuft, weiß ich derzeit nicht.
In meinen Tests hatte ich mehrere Male die Probleme, dass die Ports z.B. 8080 oder 8081 als belegt gekennzeichnet wurden.
Um herauszufinden, welche Anwendungen die Ports belegen, natürlich können das auch laufende Container sein, ist folgender Befehl hilfereich:
Das Ergebnis sieht so aus:
Somit ist für mich klar, dass ich den Port 8081 nehme.
Wie ich mit den Ports überhaupt umgehen muss, weiß ich selber noch nicht, wenn es sich um Webanwendungen handelt.
Erstellung eines Volums.
Volums sind dafür da, um eigene Daten aufzunehmen. Damit diese nicht direkt in einen Container erfasst werden, legt man unter /usr/share zum jeweiligen Programm, z.B. nginx, ein Volume an.
Die Syntax wäre in diesem Beispiel wie folgt:
Code:
sudo docker run --name my-nginx -v /some/content:/usr/share/nginx/html:ro -d nginx
some-nginx = Name des Containers
-v = ein Volume anhängen und deklarieren
-d = Dienst läuft im Hintergrund
nginx = Image
ro = read only
Hinweis:
In einem Dockercontainer sind nur die wichtigsten Pakete enthalten. Will man eine Textdatei erstellen, aber ein Editor ist nicht verfügbar, kann man pragmatisch folgendes machen:
Code:
echo "Hallo Docker!" > index.html
Damit erstellt man eine Datei, die dann verwendet werden kann. Will man künftig mehr in dem Container machen, empfiehlt es sich, einen Editor zu installieren (und daraus dann ein eigenes Build zu machen). Das wird so aber nicht empfohlen (?). Insgesamt ist das der denkbar schlechteste Weg.
Fazit:
Mit docker exec in einen Container zu gehen und dort Daten zu bearbeiten ist nicht gut und sollte so nicht gemacht werden.
Die Anwendungsdaten werden im Container nicht gespeichert. Sobald der Container beendet wird, sind die Daten weg. Daher müssen Volumes angelegt werden, die die Anwendungsdaten speichern udn vorhalten.
Um ein Volume zu erzeugen, ist folgender Befehl notwendig:
Code:
sudo docker volume create
Dieser Befehl erzeugt einen langen Name aus Zufallszahlen/-ziffern. Man kann den Volumennamen auch vorgeben:
Code:
sudo docker volume create html
Mit dem ls-Befehl kann ich mir die vorhandenen Volumes anzeigen lassen:
Code:
sudo docker volume ls
Das läuft analog zu den Images und den Containern.
Um nun das erzeugte Volume mit dem Namen html in den nginx-Container zu bringen, wird eine zweite Instanz aufgemacht und ein weiterer Port eröffnet (nicht zwingend erforderlich, nur zur Demonstration):
Code:
sudo docker run --name myvol-nginx -p 8081:80 -v html:/usr/share/nginx/html:ro -d nginx
ro heißt readonly.
Das erzeugte Volume liegt hier:
Zitat:/var/lib/docker/volumes
Dieses Verzeichnis kann ein Normaluser, selbst wenn er in der Gruppe docker ist, nicht sehen (sudo -s)
WICHTIG:
Selbst wenn der Container zerstört wird, bleibt das Volume erhalten. Wichtig ist dann dabei, dass das Verzeichnis /usr/lib/docker gesichert wird, wenn in diesem Verzeichnis Nutzer- und Anwendungsdaten für die weitere Verarbeitung gespeichert werden, also produktiv genutzt werden.
Die Volumes müssen nicht unbedingt im Docker-Verzeichnis liegen, sondern können an jeder beliebigen Stelle gespeichert werden. Dazu wäre dann z.B. dem Volume HTML das Verzeichnis voranzustellen (Beispiel): /home/django/dockervolume/HTML
Die Prozesse, die innerhalb der Container laufen, müssen allerdings die Berechtigungen auf dieses Verzeichnis haben.
Docker und Netzwerke
Docker erzeugt ein eigenes Netzwerk: docker0
Code:
ifconfig docker0
Docker hat verschiedene Netzwerke, die man sich so anzeigen lassen kann:
Code:
docker network ls
Beispiel, wie zwei Container kommunizieren.
Ein Blogsystem auf Basis WordPress-Blogsystem
- Container mit Webserver und WordPress
- Container mit Datenbank MySQL / MariaDB
Container für Datenbank:
Code:
docker run --name test-mysql -e MYSQL_ROOT_PASSWWORD=meinpasswort -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wp -e MYSQL_PASSWORD=meinpasswort -d mysql:5.7
Container für WordPress / Webserver
Code:
docker run --name wordpress --link test-mysql:test-mysql -p 8082:80 -d wordpress
Hinweis:
Zitat:--link anstelle von --name
Dieser Part "test-mysql:test-mysql" bedeutet, dass der Container test-mysql auch als test-mysql angesprochen werden. Soll dieser Name dann anders lauten, müsste er angegeben werden (z.B. test-mysql:test-worpress).
Hinweis:
Docker hat einen eigenen DNS-Server laufen.
Für das obige Beispiel würde im Browser, da wir mit WordPress arbeiten wollen, folgendes einzugebenn sein:
Zitat:localhost:8082
Sodann würde die Installation von WordPress erfolgen.
Die Daten von WordPress werden in der Datenbank abgespeichert. WordPress und die Datenbank sind in zwei Containern aufgeteilt. Um mit den eingegebenen Daten weiter arbeiten zu können, müssten die Daten in ein Volume übertragen werden
Wie das geht, weiß ich noch nicht!
Wenn z.B. WordPress vom Rest der Welt trennen möchte, dann kann das über ein eigenes Docker-Netzwerk erfolgen. Das sieht dann so aus:
Code:
docker network create --driver bridge test-bridge
Prüfen, ob das Netzwerk angelegt ist bzw. welche vorhanden sind, kann man mit:
Code:
docker network ls
Dieses neue Network kann man an den Run-Befehl für mysql hängen:
Code:
docker run --name test-mysql --network=test-bridge -e MYSQL_ROOT_PASSWWORD=meinpasswort -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wp -e MYSQL_PASSWORD=meinpasswort -d mysql:5.7
Hinweis:
Es gibt den inspect-Befehl. Dieser kann auf das Netzwerk angewandt werden. Um das neue Netzwerk zu inspizieren, ist folgendes notwendig:
Code:
docker network inspect test-bridge
Man kann also in das Netzwerk "hineinschauen".
Wie kann man Docker vereinfachen?
Contaner mit Compose einrichten
Mehrere Container nebeneinander betreiben.
Docker-Compose ist ein Python-Script (offizell von Docke unterstützt), mit dem vereinfacht mehrere Container aufgebaut und miteinander verbunden werden können.
Ein Compose-File ist wie folgt strukturiert (Beispiel MySQL-Container)
Zitat:version: '3'
services:
db:
image: mysql:5.7
volumes:
- ./data/db/:/var/lib/mysql
restart: always
ports:
- "3306:3306"
environment:
MYSQ_ROOT_PASSWORD: secret123root
Die Inhalte sind quasi die gleichen wie in einem run-Befehl.
Die Aussage ist, dass selbst, wenn nur ein Container laufen soll, eine Compose-File nützlich ist.
Der data-Ordner des Volume liegt in dem Ordner, aus dem das Compose-File aufgerufen wird. Der Punkt weist auf die relative Lage hin. Hat mein einen eigenen Bereich auf der lokalen Festplatte eingerichtet, ruft man das File eben von dort aus auf.
Für das Beispiel aus dem Netzwerkabschnitt (WordPress und MySQL) sieht das Compose-File wie folgt aus:
Zitat:version: '3'
services:
db:
image: mysql:5.7
volumes:
- ./data/db/:/var/lib/mysql
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: secret123root
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: 12345wordpress54321
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "80:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: 12345wordpress54321
working_dir: /var/www/html
volumes:
- ./data/wordpress:/var/www/html/wp-content
portainer:
image: portainer/portainer
restart: always
ports:
mehr sehe ich nicht, scheint ein volume zu sein, ist wohl eine grafische Oberfläche gedacht, also nicht in der Konsole wichtig.
So wird die yml-Datei, in der das Compose-File abgespeichert wurde, ausgeführt:
Code:
docker-compose up
- up = starten
- stop = stoppen
- down = herunterfahren (Container werden dabei sofort gelöscht)
Damit wird wohl alles an Compose-Files gestartet.
Die Ausführung dieses Befehl ist sichtbar, da die Option -d nicht mit angegeben worden ist.
Ansonsten könnte man bei der Sichtbarkeit die einzelnen Aktionen sehen, die ausgeführt würde. Es gibt dann wohl, sobald der Datanbankserver oben ist mit der Installation von Wordpress im Browser.
Hinweis:
In einer yml-Datei ist die Einrückungstiefe immer 2 Leerzeichen. Man kann auch Tabs verwenden, aber zwei Leerzeichen sind wohl Standard.
Um z.B. auf der Shell in die Container mit dem exec-Befehl einzusteigen, kann folgender Befehl genutzt werden:
Code:
docker-compose excec db sh
Damit ist man im Container anstelle des komplexen Befehlaufrufes aus den Anfängen.
Die grafische Oberfläche für Docker
Portainer ist eine bekannte grafische Oberfläche
Sofern im Compose-File der Portainer integriert ist, kann man in der Adressezeile des Browsers über den Port 9000 die Webseite erreichen.
Zitat:localhost:9000
Ich unterstelle derweil, dass das möglich ist, denn in dem Beispiel bei Heise wird mittlerweile eine echte Domain genutzt. Sollte aber auch mit localhost funktionieren.
Zertifikate erstellen
Die Anwendungen, die man in Docker erstellt, kann man sind Internet bringen. Man muss dafür aber vieles beachten, um die Sicherheit zu gewährleisten. Mit Zertifikaten kann man das erreichen.
Eine Grundlage ist z.B. Watchtower (wird niht mehr entwickelt, es gibt was neues) und gehört zu vorherigen Compose-File.
Watchtower ein Image, welches sich um die Aktualisierung von Images kümmert, was durch Docker selber nicht geleistet wird.
Code:
watchtower:
image: v2tec/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 30
Um von außen auf die Anwendung schauen zu können, wird folgendes benötigt (Revers-Server/Proxy oder so ähnlich)
Für das nachfolgende Beispiel muss der WordPress-Container angepasst werden, da diese keine Ports mehr freigeben darf (wird weiter unten mit 80 und 443 gemacht):
Code:
wordpress:
depends_on:
- db
image: wordpress:php7.1
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: 12345wordpress54321
LETSENCRYPT_HOST: mlsjam.leipsieb.de
LETSENCRYPT_EMAIL: mls@ct.de
VIRTUAL_HOST: mlsjam.leipsieb.de
VIRTUAL_PORT: 80
working_dir: /var/www/html
volumes:
- ./data/wordpress:/var/www/html/wp-content
Ob das auch auf localhost läuft, weiß ich derzeit nicht.
Code:
nginxproxy:
image: jweilder/nginx-proxy
restart: unless-stopped
volumes:
- ./data/certs:/etc/nginx/certs
- ./conf:/etc/nginx/conf.d
- ./dhparam:/etc/nginx/dhparam
- ./data/vhosts:/etc/nginx/vhost.d
- ./data/html:/usr/share/nginx.html
- /var/run/docker.sock:/tmp/docker.sock
ports:
- 80:80
- 443:443
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
nginxproxy_comp:
image: jrcs/letsencrypt_nginx_proxy_companion
restart: unless_stopped
depends_on:
- nginxproxy
volumes:
- ./data/certs:/etc/bginx/certs:rw
- ./conf:/etc/nginx/conf.d
- ./dhparam:/etc/nginx/dhparam
- ./data/vhosts:/etc/nginx/vhost.d
- ./data/html:/usr/share/nginx.html
- /var/run/docker.sock:/tmp/docker.sock:ro
In meinen Tests hatte ich mehrere Male die Probleme, dass die Ports z.B. 8080 oder 8081 als belegt gekennzeichnet wurden.
Um herauszufinden, welche Anwendungen die Ports belegen, natürlich können das auch laufende Container sein, ist folgender Befehl hilfereich:
Code:
sudo lsof -i -P -n | grep 8080
Das Ergebnis sieht so aus:
Somit ist für mich klar, dass ich den Port 8081 nehme.
Wie ich mit den Ports überhaupt umgehen muss, weiß ich selber noch nicht, wenn es sich um Webanwendungen handelt.