Docker
Docker ist eine Containerplattform.
Installation
Quelle: https://docs.docker.com/engine/install/ubuntu/
Man holt sich den Key des Repos, installiert diesen und fügt das Repo hinzu.
sudo apt-get update sudo apt-get install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg # Add the repository to Apt sources: echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update
Danach wird Docker installiert.
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Um die Installation und den Docker-Daemon zu testen, holt man sich den ersten Container und startet diesen.
docker run hello-world
Grundsätzlich kann man die Installation nun so belassen. Alle Benutzer können, wenn sie dies dürfen, per sudo
Container bedienen.
Dies ist so, da der Daemon über einen Unix-Socket und nicht über einen TCP-Port erreichbar ist. Der Socket gehört dem Benutzer „root“ und der Gruppe „docker“.
Soll jeder Benutzer dies machen dürfen, auch ohne sudo
, so fügt man diesen der, bei der Installation hinzugefügten, Gruppe „docker“ hinzu.
sudo usermod -aG docker <BENUTZER>
Hat man docker mit sudo
bedient und hat sich danach der Gruppe „docker“ hinzugefügt, so müssen noch die Rechte des eigenen Docker-Verzeichnisses angepasst werden.
mkdir -p /home/<BENUTZER>/.docker sudo chown -R <BENUTZER>:<BENUTZERGRUPPE> /home/<BENUTZER>/.docker sudo chmod -R g+rwx /home/<BENUTZER>/.docker
Konfiguration
Die Konfiguration des Daemons wird mit Startparametern geregelt.
Diese werden normalerweise über die Datei /etc/docker/daemon.json
gesetzt.
Bei Betriebssystemen mit „Systemd“ als init-System werden die Parameter direkt in Systemd eigetragen.
Dazu erstellt man eine override.conf mit folgendem Befehl:
systemctl edit docker.service
Nun setzen wir z.B. den DNS-Server welcher an die Container übergeben werden soll.
Der Inhalt der override.conf sieht wie folgt aus:
[Service] ExecStart= ExecStart=/usr/bin/dockerd --ip=<IP_DES_HOSTS> --dns=1.1.1.1 --dns=8.8.8.8 --dns-search="dns.domain.tld" -H fd://
Die leere „ExecStart=“ Zeile ist wichtig, da Systemd erst die Startsequenz löscht um sie dann neu zu definieren.
Nun noch Systemd die Änderungen mitteilen und dann den Docker-Daemon neustarten.
systemctl daemon-reload systemctl restart docker
Note that the empty ExecStart= is required, as systemctl only will overrule the ExecStart if it is cleared first.
Autostart der Container nach Boot
Damit die Docker Container nach einem reboot des Docker Hosts automatisch starten, können folgende Methoden angewandt werden:
- starten über Prozessmanager wie
systemd
- starten über Docker Restart Policies
Systemd
Quelle: https://mehmandarov.com/start-docker-containers-automatically/
Per Befehl vi /etc/systemd/system/docker-<CONTAINERNAME>.service
einen neuen Service erstellen
docker-<CONTAINERNAME>.service
[Unit] Description=<NAME_OF_CONTAINER> Requires=docker.service After=docker.service [Service] Restart=always ExecStart=/usr/bin/docker start -a <CONTAINERNAME> ExecStop=/usr/bin/docker stop -t 2 <CONTAINERNAME> [Install] WantedBy=local.target
Erklärung:
ExecStart=/usr/bin/docker start -a
→ startet den Container im „attach“ Modus
ExecStop=/usr/bin/docker stop -t 2
→ wartet 2 Sekunden auf den Stop des Container, bevor dieser gekillt wird
Nach dem Erstellen des Service diesen noch systemd
bekannt machen und aktivieren:
systemctl daemon-reload systemctl enable docker-<CONTAINERNAME>.service
Gestartet werden kann der neue Service über die üblichen start
und stop
Kommandos.
Restart Policies
Quelle: https://docs.docker.com/config/containers/start-containers-automatically/
Mit dem run
befehl dem Container sagen, welche restart Policy er erhalten soll:
docker run --restart [no|on-failure|always|unless-stopped]
Restart Policy | Beschreibung |
---|---|
no | Do not automatically restart the container. (the default) |
on-failure | Restart the container if it exits due to an error, which manifests as a non-zero exit code. |
always | Always restart the container if it stops. If it is manually stopped, it is restarted only when Docker daemon restarts or the container itself is manually restarted. (See the second bullet listed in restart policy details) |
unless-stopped | Similar to always, except that when the container is stopped (manually or otherwise), it is not restarted even after Docker daemon restarts. |
Mit foldendem Befehl kann man sehen welche Restart Policy aktuell im jew. Container gesetzt ist:
docker inspect graphite| jq '"Container: \(.[].Name)","Restart-Policy: \(.[].HostConfig.RestartPolicy.Name)"'
Debug
Mit der Startoption -D|–debug
kann man das Debugging bei Docker einschalten.
Danach startet man die Log-Ansicht für einen Container wie folgt:
docker logs [<OPTIONEN>] <CONTAINER_NAME>
RUN, ENTRYPOINT, CMD
Die Befehle RUN
, ENTRYPOINT
und CMD
werden im Dockerfile
unterschiedlich benutzt.
Grundsätzlich können diese Befehle als Exec und Shell Format übergeben werden.
Exec:
Beispiel
[RUN|ENTRYPOINT|CMD] ["<BEFEHL>", "<PARAMETER1>", "<PARAMETER2>"]
- Im Exec Format wir der Befehl direkt so ausgeführt. Mit
ENV
gesetzte Variablen werden nicht übersetzt. Dazu muss der Befehl als Parameter für eine Shell angegeben werden (wie beim Shell Format) - Wenn Bash ausgeführt werden muss, so sollte dies im Exec Format geschehen. Hier lassen sich Parameter eindeutig übergeben.
Shell:
Beispiel
[RUN|ENTRYPOINT|CMD] <BEFEHL> <PARAMETER1> <PARAMETER2>
- Im Shell Format wird der Befehl mit Shell (
/bin/sh -c <BEFEHL>
) ausgeführt. - kann verwendet werden um mehrere gleiche Befehlszeilen zu minimieren
Beispiel:apt update && apt install -y \ nginx \ mysql
Befehl | Beschreibung | kann mehrmals verwendet werden |
---|---|---|
RUN | * wird verwendet um Befehle beim erstellen eines Images auszuführen | ja |
Entrypoint | * wird verwendet um Befehle nach dem Start des Containers auszuführen * wird auch ausgeführt wenn der docker run Befehl einen Standard Befehl am Ende ausführt * wenn im Shell Format angegeben, wird jeder CMD Befehl ignoriert | ja |
CMD | * wird verwendet um eine Standard Befehl nach dem start des Containers abzusetzen * Wenn beim docker run Befehl ein Standard Befehl am Ende angegeben wird, wird CMD ignoriert * Kann auch verwendet werden um nur Parameter an ENTRYPOINT zu übergeben, wenn kein Standard Befehl beim docker run übergeben wird, wird der ENTRYPOINT ausgeführt | nein (bzw. nur der letzte CMD -Befehl wird ausgeführt) |
Konfigurationsparameter
Mögliche Parameter für Konfigurationen können in den Reference-Docs unter docker.com eingesehen werden https://docs.docker.com/reference/.
Nützliche Befehle
dem Befehl docker
können verschiedene Parameter übergeben werden.
Parameter | Beschreibung |
---|---|
–version | zeigt die Version von Docker in Kurzfassung |
version | zeigt die Version von Docker ausführlich |
ps | zeigt laufende Container |
build -t <IMAGE_NAME> . | erstellt ein Image mit angegebenen Namen über das im aktuellen Ordner befindlichen Dockerfile |
run | startet ein Image |
run -p 8080:80 <IMAGE_NAME> | startet ein Image wo der, von aussen, erreichbare Port 8080 auf den, im Container erreichbaren, Port 80 gemappt wird |
run -d <IMAGE_NAME> | startet ein Image im detached Modus (das Prompt ist wieder frei) |
container ls | listet alle laufenden Container auf |
container ls -a | listet alle Container auf (gestartet oder gestoppt) |
container stop <CONTAINER_ID> | stoppt den jew. Container (wie shutdown) |
container kill <CONTAINER_ID> | erzwingt das stoppen des jew. Containers |
container rm <CONTAINER_ID> | löscht den jew. Container vom Server |
container rm $(docker container ls -a -q) | löscht alle Container vom Server |
image ls | zeigt vorhandene Images |
image ls -a | zeigt alle Images |
image rm <IMAGE_ID> | löscht das jew. Image vom Server |
image rm $(docker image ls -a -q) | löscht alle Images vom Server |
logs <CONTAINER_ID> | zeigt logs über den jew. Container |
inspect <CONTAINER_ID> | zeigt ausführliche Infos über den jew. Container |
attach <CONTAINER_ID> | Verbindet sich zum Container zum Standard Input/Output Terminal (detach per STRG+P und danach STRG+Q) |
exec -it <CONTAINER_ID> /bin/bash | Verbindet sich zu einer Bash-Shell zum Container |
Netzwerk
Docker verfügt über folgende Treiber für die Netzwerkanbindung eines Containers:
Treiber | Beschreibung |
---|---|
bridge | Das ist der Standard, wenn ein Container erstellt wird; befindet sich im NET-Netz hinter der Host Adresse |
host | Nutzt die Netzwerkschnittstelle des Hosts und ist direkt an dessen IP-Adresse gebunden |
overlay | Wird verwendet wenn mehrere Docker Hosts sich ein Container-Netzwerk teilen sollen |
macvlan | Layer 3 Netzwerk; kann verwendet werden um Container direkt an das Netzwerk mit einer eigenen IP-Adresse anzubinden (z.B. mehrere VLANs ) Es können für die Container Netzwerschnittstelle IP-Adressen oder MAC-Adressen definiert werden |
iplan | ähnlich wie macvlan der nur Layer 2 |
Möchte man die IP-Adressen eines Containers ausgeben lassen, dann macht man das mit docker container inspect <CONTAINER_NAME>
.
Sollen alle IP-Adressen aller Container ausgegeben werden, so kann man diesen Befehl verwenden.
Hierbei muss beachtet werden, wie der Container angebunden ist, so ist der Befehl ggf. anzupassen.
docker inspect -f '{{.Name}}-{{range .NetworkSettings.Networks}} {{.IPAddress}}{{end}}' $(docker ps -aq)
MACVLAN
Bei einem macvlan Netzwerk, werden die Container direkt im Netzwerk behandelt wie jeder normale Host. Sie sind quasi mit einer eigenen Netzwerkschnittstelle im Netzwerk präsent.
Container können mit dem Parameter ip_address
(docker-compose) eine eigene feste IP-Adresse besitzen.
Soll ein DHCP-Server die IP-Adressen verwalten, so muss man bedenken, dass sich die MAC-Adresse eines Containers ändert, wenn dieser oder der Docker-Daemon neugestartet wird.
Dies kann mit dem Parameter mac_address
(docker-compose: IST IN VERSION 3 DEPRECATED) angepasst werden und eine eindeutige MAC-Adresse vergeben werden.
MAC-Adressen werden vom Docker-Daemon generiert. Hier ein Auszug aus der Docker Reference:
By default, the MAC address is generated using the IP address allocated to the container. You can set the container’s MAC address explicitly by providing a MAC address via the --mac-address parameter (format:12:34:56:78:9a:bc). Be aware that Docker does not check if manually specified MAC addresses are unique.
Eine einzigartige MAC-Adresse kann sich man aber relativ leicht zusammenstellen.
Wie immer geben die ersten 3 Stellen der MAC-Adresse den Hersteller (also die OUI ⇒ Organizationally Unique Identifier, „organisatorisch eindeutige Kennung“) an, bei Docker ist dies aber nicht der Fall.
Ein Docker-Daemon hat in diesem Fall die ersten 2 Stellen generiert, es geht also nur um die letzten 4 Stellen.
Dazu nimmt man einen Dezimal / Hexadezimal Rechner und wandelt die letzten 4 Oktette der IP-Adresse des Containers um.
Beispiel:
generierte MAC-Adresse: 02:42:c0:a8:8a:0b
Hier sind die Stellen 02:42
die festen Angaben, die letzten 4 würden in Dezimal folgendes ergeben 192:168:138:11
.
Dies ist die IP-Adresse des Containers.
Hat man einen DCHP-Server, kann man bei diesem eine IP-Adresse für einen Container reservieren.
Danach rechnet man diese in Hexadezimal um und erhält somit die eindeutige MAC-Adresse.
Route von/zu Docker-Host
Generell sind Docker Container, welche sich in einem macvlan befinden, vom Docker Host isoliert (obwohl beide vielleicht im selben Subnetz sind.
Damit man die Verbindung wiederherstellen kann, muss eine Netzworkbridge mit einer entspr. Route zum Container/-Netzwerk erstellt werden.
Hier ein Beispiel (Quelle: https://www.networkshinobi.com/docker-host-cant-access-containers-running-on-macvlan/):
ip link add <NAME_CUSTOM_BRIDGE_DEVICE> link <PHYSICAL_LINKED_DEVICE_TO_NETWORK> type macvlan mode bridge ip addr add <IP_ADDRESS_FROM_MACVLAN> dev <NAME_CUSTOM_BRIDGE_DEVICE> ip link set <NAME_CUSTOM_BRIDGE_DEVICE> up ip route add <IP_ADDRESS_FROM_CONTAINER_IN_MACVLAN>/32 dev <NAME_CUSTOM_BRIDGE_DEVICE>
Images und Container
Images werden in Layer aufgeteilt. Einzelne Anweisungen im Dockerfile führen dazu, dass verschieden viele Layer erzeugt werden. Diese Layer sind alle schreibgeschützt.
Erst wenn der Container mit seinem Befehl gestartet wird, erzeugt er einen neuen eigenen letzen Layer, welcher beschrieben werden kann.
Dieser enthält die Daten welche zur Laufzeit hinzugekommen/geändert sind/wurden.
Erstellen
Um ein Image zu erstellen, benötigt man eine Datei namens Dockerfile
. Darin stehen die Anweisungen zum erstellen eines Containers.
Alle benötigten Dateien zum Erstellen eines Images, sollten sich in einem eigenen Ordner befinden.
Beispiel zum Erstellen eines Images mit Nginx und PHP:
mkdir nginx-php cd nginx-php
Konfigurationsdateien
Folgende Dateien müssen erstellt und mit Inhalt gefüllt werden.
Erklärung
Datei | Beschreibung |
---|---|
Dockerfile | * steuert das Erstellen des Images und das Startverhalten des Containers |
package.list | * enthält die, in das Image, zu installierenden Pakete |
startup.sh | * Startscript welches nach dem Starten des Containers ausgeführt wird * hier werden die Daemons für nginx und php gestartet * der letzte Befehl ist dafür da, damit das Script und somit auch der Container dauerhaft läuft |
nginx.conf | * Konfiguration für nginx |
my-website-conf | * Konfiguration für Webseite |
fastcgi-php.conf | * Konfiguration für php und fastcgi |
snakeoil.conf | * Konfiguration für die SSL Verschlüsselung mit Snakeoil Zertifikaten |
ssl-cert-snakeoil.key | * SSL Zertifikat von Snakeoil |
ssl-cert-snakeoil.pem | * SSL privater Schlüssel von Snakeoil |
ssl-conf | * Konfiguration für SSL verschlüsselte Webseiten |
dhparam.pem | * Diffie Hellmann Schlüssel |
index.php | * Startseite |
phpinfo.php | * PHP-Info Webseite |
hallo.html | * SSL verschlüsselte Webseite |
Dockerfile
FROM ubuntu:bionic # Define environment variable ENV WWW_DIR /var/www/html ENV TERM xterm ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin ENV DEBIAN_FRONTEND noninteractive # set Timezone with `--build-arg TIMEZONE=Europe/Berlin` in `docker build` ARG TIMEZONE # Set the working directory to /var/www/html WORKDIR /var/www/html # Copy files ADD *.html /var/www/html/ ADD *.php /var/www/html/ ADD package.list /tmp ADD timezone /etc # Install any needed packages specified in requirements.txt RUN \ apt update && \ apt upgrade -y && \ apt install -y apt-utils && \ cat /tmp/package.list | xargs apt install -y # set Timezone RUN if [ ! -z "${TIMEZONE}" ]; \ then ln -sf /usr/share/zoneinfo/$TIMEZONE /etc/localtime && \ dpkg-reconfigure -f noninteractive tzdata; \ fi # Create directories RUN mkdir -p /etc/ssl/certs /etc/ssl/private /var/log/nginx # Install Snakeoil Cert and Key ADD ssl-cert-snakeoil.pem /etc/ssl/certs ADD ssl-cert-snakeoil.key /etc/ssl/private # Copy Nginx Configs ADD nginx.conf /etc/nginx/ ADD fastcgi-php.conf /etc/nginx/snippets/ ADD snakeoil.conf /etc/nginx/snippets/ ADD dhparam.pem /etc/nginx/snippets/ ADD ssl-conf /etc/nginx/sites-available/ ADD my-website-conf /etc/nginx/sites-available/ ADD startup.sh /usr/local/bin RUN \ ln -s /etc/nginx/sites-available/my-website-conf /etc/nginx/sites-enabled && \ unlink /etc/nginx/sites-enabled/default # Define mountable directories. VOLUME ["/etc/nginx", "/var/log", "/var/www/html"] # Make ports 80 and 443 available EXPOSE 80 EXPOSE 443 ENTRYPOINT ["/bin/bash", "-c", "startup.sh"]
package.list
vim rsyslog nginx php-fpm fcgiwrap openssl
startup.sh
#!/bin/bash while ! pgrep nginx; do service nginx start sleep 1 done while ! pgrep php-fpm; do service php7.2-fpm start sleep 1 done tail -f /dev/null
nginx.conf
user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; # multi_accept on; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # SSL Settings ## ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; ## FCGI: Detect when HTTPS is used map $scheme $fastcgi_https { default off; https on; } upstream php { server unix:/var/run/php/php7.2-fpm.sock; } upstream fcgiwrap { server unix:/var/run/fcgiwrap.socket; } ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
my-website-conf
server { listen 80; server_name _; root /var/www/html; index index.html index.htm index.php; location / { index index.html index.htm index.php; try_files $uri $uri/ /index.php; } location ~ \.php$ { include snippets/fastcgi-php.conf; try_files $fastcgi_script_name =404; } # We don't want to allow the browsers to see .hidden linux/unix files location ~ /\. { deny all; access_log off; log_not_found off; } } server { listen 443 ssl; include snippets/snakeoil.conf; include /etc/nginx/sites-available/ssl-conf; root /var/www/html; index index.html index.htm index.php; server_name _; location / { index index.php; try_files $uri $uri/ /index.php; } location ~ \.php$ { include snippets/fastcgi-php.conf; try_files $fastcgi_script_name =404; } # We don't want to allow the browsers to see .hidden linux/unix files location ~ /\. { deny all; access_log off; log_not_found off; } }
fastcgi-php.conf
# regex to split $uri to $fastcgi_script_name and $fastcgi_path fastcgi_split_path_info ^(.+\.php)(/.+)$; # Check that the PHP script exists before passing it #try_files $fastcgi_script_name =404; # Bypass the fact that try_files resets $fastcgi_path_info # see: http://trac.nginx.org/nginx/ticket/321 set $path_info $fastcgi_path_info; fastcgi_param PATH_INFO $path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REQUEST_SCHEME $scheme; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200; fastcgi_index index.php; fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; fastcgi_read_timeout 240;
snakeoil.conf
# Self signed certificates generated by the ssl-cert package # Don't use them in a production server! ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl-cert-snakeoil.pem
: SSL-Zertifikat kann vom lokalen Docker Host kopiert werdenssl-cert-snakeoil.key
: SSL privater Schlüssel kann vom lokalen Docker Host kopiert werdenssl-conf
#SSL-Protocols ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #HSTS Security add_header Strict-Transport-Security max-age=15768000; ssl_session_timeout 1d; ssl_session_cache shared:SSL:10m; # openssl dhparam -out dhparam.pem 2048 ssl_dhparam /etc/nginx/snippets/dhparam.pem; ##ssl_protocols TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK'; ssl_prefer_server_ciphers on;
dhparam.pem
Diese Datei muss überopenssl
einmalig, auf dem Docker-Host, erzeugt werdenopenssl dhparam -out dhparam.pem 2048
index.php
: Hier noch die IP Adresse oder Hostnamen anpassen<html> <head> <title>NGINX im Docker-Container</title> </head> <body> <h1>Testseiten</h1> <li><a href="http://<IP_ADDRESS>/phpinfo.php">zeige PHP-Info</a></li> <li><a href="https://<IP_ADDRESS>/hallo.html">zeige PHP-Info</a></li> </body> </html>
phpinfo.php
<?php // Zeigt alle Informationen (Standardwert ist INFO_ALL) phpinfo(); ?>
Build and Run
Nun kann man das Docker-Image bauen lassen. Dazu führt man folgenden Befehl aus:
docker build --build-arg TIMEZONE=Europe/Berlin -t <NAME_DES_IMAGES> .
Mit folgendem Befehl sieht man das nun erstellte Image
docker image ls
Das Images ist nun erstellt. Nun kann man seinen Docker-Container starten.
docker run -d -p 80:80 -p 443:443 --name nginx <IMAGE_NAME>:<TAG>
Zur Erklärung der Parameter:
-d
steht für „detach“. Der Container wird dann im Hintergrund ausgeführt.-p
stellt Ports welche innerhalb des Containers laufen nach außen bereit. <PORT_AUSSEN>:<PORT_IM_CONTAINER>
Der Container sollte nun dauerhaft laufen und die Ports 80 und 443 nach außen bereitstellen.
Man kann nun im Webbrowser die URL http://<IP_DES_DOCKER_HOSTS> eingeben und die Webseite der index.php sehen.
Der folgende Befehl zeigt alle laufenden Container.
docker container ls
Dieser Befehl beendet den jew. Container
docker container stop <ID>
Volumes
Damit man wegen Konfigurationsänderungen nicht ständig zum Container verbinden muss, erstellt man sich Docker-Volumes und mountet diese mit den Volumes welche im Dockerfile angegeben wurden.
Die Volumes werden folgendermaßen angelegt:
docker volume create <VOLUME_NAME>
Der Docker Container wird dann so gestartet:
docker run -d -p 80:80 -p 443:443 -v nginx-nginx:/etc/nginx -v nginx-log:/var/log -v nginx-html:/var/www/html <IMAGE_NAME>:<TAG>
Zur Erklärung der Parameter:
-v
mountet Verzeichnisse aus dem Container in Volumes auf dem Docker-Host oder anderer Container. <VOLUME_NAME>:<ZIELPFAD_IM_CONTAINER>- im Dockerfile werden Verzeichnisse im Parameter
VOLUME
gekennzeichnet, welche als mountpoints gelten.
Docker umziehen
Wenn Container/Images auf einen anderen Host umziehen sollen, so muss man beachten wie die Laufzeitdaten gesichert werden können.
Laufzeitdaten können in Images oder aber auch auf Volumes liegen.
Weiterhin ist es absolut wichtig, dass der Container wieder so gestartet wird, wie auf dem ursprünglichen Host.
Man muss also den Befehl für docker run…
haben oder diesen nachbilden. Mit docker inspect..
werden detailierte Angaben zum Container ausgegeben.
Darüber kann man sich sein run Befehl zusammenbasteln.
- Volumes: Laufzeitdaten können vom Pfad
/var/lib/docker/volumes/<VOLUME_NAME>
gesichert werden.
Auf dem neuen Host einfach in ein neues Volume erstellen und die Daten dort hineinkopieren/rsyncen/… Dann das Image, als Tar, vom alten auf den neuen Host umziehen (docker save/load
).
Container erstellen (docker run
) und auf das neue Volume verweisen. - Container: Daten des Images und die Laufzeitdaten liegen im erstellten Tar. Dann Tar importieren und den Container mit dem neuen Image starten.
- Image: Wenn ein Image umzieht, beinhaltet das Tar nur die Daten des Images. Mit dem Befehl
docker commit
lassen sich Imagedaten und Containerdaten zusammenführen. So entsteht ein neues eigenes Image.
Dies wie oben beschrieben umziehen und den Container mit dem eigenen Image starten.
- Save/Load
- sichern
docker save -o <OUTPUT_FILE_NAME>.tar <IMAGE_ID>
- importieren
docker load -i <INPUT_FILE_NAME>.tar
- Export/Import
- sichern
docker export -o <OUTPUT_FILE_NAME>.tar <CONTAINER_ID>
- importieren
docker import <INPUT_FILE_NAME>.tar
Portainer
Portainer ist ein Docker Management Tool, welches auch als Container läuft.
Siehe https://www.portainer.io/.
Installation
docker volume create portainer_data $ docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
Upgrade
docker stop portainer docker pull portainer/portainer docker container rm portainer
Danach einfach Portainer wie bei der Installation beschrieben, starten.