Einführung
WordPress ist eines der beliebtesten Content-Management-Systeme (CMS) auf dem Markt. Statistisch gesehen betreibt es über 39 % aller Websites, die Sie im World Wide Web sehen. Es ist eine beliebte Wahl aufgrund seiner Erweiterbarkeit durch Plugins und seines flexiblen Template-Systems. Es ermöglicht Ihnen, sein Aussehen in Sekundenschnelle zu ändern. Darüber hinaus kann die Verwaltung über die Weboberfläche erfolgen, ohne dass viel technisches Know-how erforderlich ist.
Zudem ist WordPress kostenlos und Open-Source und basiert auf einer MySQL-Datenbank mit PHP-Verarbeitung. Sie können WordPress auf einem LAMP-Stack (Linux, Apache, MySQL und PHP) bereitstellen oder einem LEMP-Stack (Linux, Nginx, MySQL und PHP). Es erweist sich jedoch als zeitaufwendig, den Stack jedes Mal neu einzurichten, wenn Sie eine Bereitstellung durchführen möchten.
Glücklicherweise haben moderne Methoden der Softwarebereitstellung wie Cloud-Computing, Docker, und Docker Compose die gesamte Entwicklererfahrung verbessert. Diese Tools vereinfachen den Prozess der Einrichtung eines beliebigen Stacks, indem sie den Aufwand für die Installation und Konfiguration einzelner Komponenten bei jeder Bereitstellung einer Anwendung vermeiden. Stattdessen schreiben Sie Konfigurationsdateien, die verwendet werden, um Images herunterzuladen, zu erstellen und in Docker-Containern auszuführen, sodass Sie Ihre Anwendung mit nur einem Befehl bereitstellen können.
Container sind leichtgewichtige, virtualisierte, portable, softwaredefinierte standardisierte Umgebungen, die es der Software ermöglichen, isoliert von anderer Software zu laufen, die auf dem physischen Host-Rechner ausgeführt wird. Mit Docker Compose können Sie mehrere Container verwalten und sicherstellen, dass sie miteinander kommunizieren. Beispielsweise müssen der Quellcode einer Anwendung und eine Datenbank kommunizieren.
In diesem Tutorial werden wir eine containerisierte WordPress-Anwendung mit mehreren Containern erstellen. Eine vollständige WordPress-App erfordert drei Container: MySQL-Datenbank, Nginx-Server und WordPress-Quellcode. Da Sicherheit bei modernen Websites Priorität hat, werden wir ein SSL-Zertifikat von Let’s Encrypt beziehen, um Ihre Installation zu sichern. Anschließend werden wir einen cron-Job einrichten, um Zertifikate regelmäßig zu überprüfen und zu erneuern, damit die Sicherheit Ihrer Website kontinuierlich gewährleistet bleibt.
Voraussetzungen
- Da es sich um ein praktisches Tutorial handelt, sollten Sie eine Installation von Ubuntu 20.04 als Ihre anfängliche Betriebsumgebung haben. Sie sollten außerdem über einen Nicht-Root-Benutzer mit sudo-Rechten verfügen. Hier ist ein Schritt-für-Schritt-Tutorial, das Ihnen bei der Einrichtung Ihres Ubuntu-Servers hilft.
- Sie müssen auch Docker installieren. Sie können sich auf dieses Tutorial beziehen, wie man Docker auf Ubuntu 18.04 installiert und bedient.
- Eine Installation von Docker Compose. Sie können Schritt 1 des Tutorials Installation und Konfiguration von Docker Compose auf Ubuntu 20.04.
- Ein registrierter Domainname ist erforderlich, um ein TLS/SSL-Zertifikat von Let’s Encrypt zu erhalten. Für dieses Tutorial verwenden wir
example.com. - Richten Sie DNS-Einträge ein, um den Datenverkehr auf Ihren VPS zu leiten. Sie benötigen zwei DNS-Einträge:
- Einen A-Eintrag mit
example.com, der auf die öffentliche IP-Adresse Ihres Servers verweist. - Einen A-Eintrag mit
www.example.com, der auf die öffentliche IP-Adresse Ihres Servers verweist.
- Einen A-Eintrag mit
Schritt 1: Definieren der Konfigurationen für den Webserver
Der Webserver enthält Ihre Website-Dateien und ermöglicht Benutzern den Zugriff auf Ihre Webanwendung. Daher ist es nur angemessen, dass wir im ersten Schritt die Konfiguration für den Webserver definieren. Wir werden eine Nginx-Serverkonfigurationsdatei definieren, die WordPress-spezifische Location-Blöcke enthält. Wir werden auch Location-Blöcke einfügen, um Let’s Encrypt-Verifizierungsanfragen an den Certbot-Client für automatische Verlängerungen des Zertifikats weiterzuleiten.
Beginnen wir mit dem Erstellen eines Verzeichnisses für das Projekt. Sie können einen Verzeichnisnamen Ihrer Wahl wählen. Wir verwenden wordpress_docker für dieses Tutorial. Geben Sie den folgenden Befehl ein, um das Verzeichnis zu erstellen und dorthin zu navigieren:
|
1 |
mkdir wordpress_docker && cd wordpress_docker |
Erstellen Sie als Nächstes mit dem folgenden Befehl ein Verzeichnis für die Nginx-Konfigurationsdateien:
|
1 |
mkdir nginx-conf |
Verwenden Sie nano, um die Datei mit dem folgenden Befehl zu öffnen:
|
1 |
nano nginx-conf/nginx.conf |
In dieser Datei werden wir grundlegende Direktiven für eine Nginx-Server-Block-Konfiguration definieren. Diese umfassen Direktiven für den Servernamen, das Dokumenten-Root-Verzeichnis und Location-Blöcke, um Certbot-Plugin-Anfragen für Zertifikate, statische Dateien und die PHP-Verarbeitung weiterzuleiten. Sie können unser Tutorial zu So sichern Sie Nginx mit Let’s Encrypt lesen, um mehr zu erfahren. Fügen Sie der Datei den folgenden Code hinzu und ersetzen Sie example.com durch Ihren registrierten Domainnamen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
server { listen 80; listen [::]:80; server_name example.com www.example.com; index index.php index.html index.htm; root /var/www/html; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } } |
Lassen Sie uns die Abschnitte definieren, die Sie hinzugefügt haben:
-
Direktiven:
listen: Es weist Nginx an, auf Port80zu lauschen. Dies ermöglicht die Verwendung des Certbot-Webroot-Plugins, um Zertifikatsanfragen zu stellen. Sobald wir ein SSL-Zertifikat erhalten haben, werden wir diese Konfiguration aktualisieren, um Port443.server_name: Dies definiert den Domainnamen, für den diese Konfiguration zuständig sein soll. Der Datenverkehr zu dem hier definierten Domainnamen wird an diesen speziellen Server-Block und somit an das Dokumenten-root.root-Verzeichnis weitergeleitet. Es definiert das Stammverzeichnis für Anfragen an den oben genannten Domainnamen. Normalerweise ist dies das Verzeichnis, das unsere eigentlichen Website-Dateien enthält. Wir haben das Verzeichnis auf/var/www/htmlfestgelegt. Es wird als ein Docker-Mountpoint erstellt während der Erstellung des Containers. Wir werden die Anweisungen für diesen Prozess innerhalb der WordPress Dockerfile.index: Dies definiert Dateien, die als Indizes oder Einstiegspunkt für Ihren Webserver bei der Verarbeitung von Anfragen verwendet werden. Wir haben index.php vor index.html verschoben, damit Nginxindex.php.
-
Location-Blöcke:
location ~ /.well-known/acme-challenge: verarbeitet Anfragen an das well-known-Verzeichnis, in dem Certbot eine temporäre Datei hinzufügt, um zu validieren, dass der DNS für die angegebene Domain auf den spezifischen Server verweist, von dem wir SSL-Zertifikate anfordern. Aus diesem Grund sollten Sie für diesen Schritt eine gültige Domain anstelle vonexample.comverwenden, die wir in diesem Tutorial nutzen.location /: nimmt URI-Anfragen entgegen und übergibt die Kontrolle an WordPressindex.phpum Argumente für die Verarbeitung anzufordern.location ~ \.php$: verarbeitet die PHP-Verarbeitung und leitet die Anfrage an den WordPress-Container weiter (wir werden in einem späteren Schritt eine Konfigurationsdatei dafür definieren). Wir haben hier spezifische Konfigurationen für das FastCGI-Protokoll definiert, da das WordPress-Docker-Image auf dem php:fpm-Image basieren wird. Nginx verwendet einen unabhängigen PHP-Prozessor für PHP-spezifische Anfragen. Wir werden denphp-fpm-Prozessor verwenden, der mit demphp:fpm-Docker-Image geliefert wird.location ~ /\.ht: verarbeitet.htaccess-Dateien, die Nginx nicht verwendet. Diedeny all-Direktive stellt sicher, dass diese Dateien niemals an Website-Besucher ausgeliefert werden.location = /favicon.ico, location = /robots.txt: wie in der Definition zu sehen, verhindert dies die Protokollierung von Anfragen an/favicon.icound/robots.txt-Dateien.location ~* \.(css|gif|ico|jpeg|jpg|js|png)$: schaltet die Protokollierung von Anfragen an statische Dateien aus und stellt sicher, dass diese zwischengespeichert werden, um die Last auf dem Server zu verringern.
Sie können die Datei nun speichern und schließen, indem Sie STRG+X, Y, dann EINGABE drücken. Damit ist der erste Schritt abgeschlossen.
Step 2: Define Environment Variables
Umgebungsvariablen sind notwendig, um die Kommunikation zwischen der WordPress-Anwendung und der Datenbank zu erleichtern. Sie stellen auch sicher, dass die Anwendungsdaten dauerhaft gespeichert werden. Die Umgebungsvariablen enthalten sensible Informationen wie Datenbank-Anmeldedaten und nicht-sensible Informationen wie Datenbankname und -host.
Aus Sicherheitsgründen ist es immer eine gute Idee, keine sensiblen Informationen zu Projekt-Repositories hinzuzufügen. Daher werden wir, anstatt die sensiblen Werte in der Docker Compose-Datei festzulegen, die MySQL-Anmeldedaten in den .env-Dateien definieren, die nicht in das Projekt-Repository übertragen werden und somit nicht der Öffentlichkeit preisgegeben werden. Öffnen Sie im Projekt-Verzeichnis root ~/wordpress_docker die Datei .env:
|
1 |
nano .env |
|
1 2 3 |
MYSQL_ROOT_PASSWORD=your_strong_root_password MYSQL_USER=your_wordpress_database_user MYSQL_PASSWORD=strong_wordpress_database_password |
Als Nächstes müssen Sie die Datei .env zu den Dateien .gitignore und .dockerignore hinzufügen, um sicherzustellen, dass sie nicht zu Ihren Repositories bzw. Docker-Images hinzugefügt wird.
Dies ist für dieses Tutorial nicht erforderlich, aber wenn Sie mit Git zur Versionskontrolle arbeiten möchten, geben Sie den folgenden Befehl ein, um das aktuelle Verzeichnis als Git-Repository zu initialisieren:
|
1 |
git init |
Öffnen Sie die Datei .gitignore mit nano:
|
1 |
nano .gitignore |
Fügen Sie die folgende Zeile hinzu:
|
1 |
.env |
Speichern und schließen Sie die Datei. Öffnen Sie als Nächstes die Datei .dockerignore mit nano:
|
1 |
nano .dockerignore |
Fügen Sie die folgende Zeile hinzu:
|
1 |
.env |
Bei dieser Gelegenheit können Sie optional weitere Dateien und Verzeichnisse hinzufügen, die mit der Entwicklung Ihrer Anwendung zusammenhängen:
|
1 2 3 |
.env .git docker-compose.yml |
Speichern und schließen Sie die Datei, wenn Sie fertig sind. Das ist alles für diesen Schritt. Fahren wir mit der Docker Compose-Definition fort.
Step 3: Configure Services with Docker Compose
Docker Compose verwendet eine docker-compose.yml-Datei, um Images zu erstellen. Diese Datei enthält Dienstdefinitionen für die vollständige Einrichtung einer Anwendung. Dienstdefinitionen sind im Grunde Anweisungen dafür, wie ein Container ausgeführt wird. Ein Dienst ist ein tatsächlich laufender Container.
Docker Compose ermöglicht es, verschiedene Dienste für Multi-Container-Anwendungen zu definieren, indem die verschiedenen Dienste über gemeinsame Netzwerke und Volumes miteinander verknüpft werden. Sie werden dies in Aktion sehen, da wir drei Container für unsere Anwendung definieren werden: Webserver, WordPress-Installation und Datenbank. Wir werden einen vierten Container hinzufügen, um den Certbot-Client für Zertifikatsverlängerungen auszuführen.
Geben Sie den folgenden Befehl ein, um die docker-compose.yml-Datei zu erstellen:
|
1 |
nano docker-compose.yml |
Die erste Zeile in einer docker-compose.yml-Datei ist die Versionsdefinition-Zeile. Wir haben für unsere 3 festgelegt. Danach können Sie mit der Definition Ihrer Dienste beginnen. Fügen Sie das folgende Code-Snippet in die Datei ein, um den db-Dienst zu definieren:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
version: '3' services: #MySQL Service db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network |
Lassen Sie uns besprechen, was wir in den db-Dienstdefinitionen unten haben:
image: bestimmt das Image, auf dem der Container basieren wird. Es ist immer besser, eine bestimmte Version anzugeben (mysql:8.0) als das Tag „latest“ zu verwenden (mysql:latest) da zukünftige Versionen von MySQL-Images mit unserer Anwendung kollidieren können, falls wir dieses Image neu erstellen. Weitere Informationen finden Sie unter Dockerfiles Best Practices in der offiziellen Dockerfile-Dokumentation.container_name: Hier geben wir den Containernamen an.restart: Diese Direktive bestimmt das Neustartverhalten des Containers. Der Standardwert istno, aber wir haben ihn so eingestellt, dass er immerneu startet, es sei denn, er wird manuell gestoppt.env_file: Diese Direktive wird verwendet, um den Speicherort der Datei mit den Umgebungsvariablen (.env) anzugeben, die von unserer Anwendung verwendet werden.environment: Wird verwendet, um zusätzliche Umgebungsvariablen anzugeben. In diesem Tutorial haben wir die VariableMYSQL_DATABASEangegeben, um den Datenbanknamen für unsere Anwendung zu enthalten. Der Datenbankname kann in derdocker-compose.yml.volumes: Wird zur Angabe von Mount-Verzeichnissen verwendet. In unserem Beispiel haben wir ein benanntes Volume namens dbdata in das Verzeichnis/var/lib/mysqlauf dem Container gemountet, welches normalerweise das Standard-Datenverzeichnis für MySQL ist.command: Diese Direktive gibt einen Befehl an, der die standardmäßige CMD-Anweisung für das Image überschreibt. Wir haben dem Standardbefehlmysqlddes Docker-Images, der den MySQL-Server im Container startet, eine Option hinzugefügt. Die von uns hinzugefügte Option ist--default-authentication-plugin=mysql_native_password, wodurch das Standard-Authentifizierungs-Plugin für MySQL so aktualisiert wird, dass es die Passwort-Authentifizierung (mysql_native_password) verwendet. Dies ist erforderlich, damit Ihre PHP- (WordPress-) Anwendung funktioniert, da sie einen Benutzernamen und ein Passwort für den Zugriff auf die Datenbank verwendet. In neueren MySQL-Versionen hat sich das Standard-Authentifizierungs-Plugin geändert. Die meisten Anwendungen verwenden jedoch die Passwort-Authentifizierung. Daher müssen Sie diese Einstellung ändern, damit die Anwendung funktioniert.networks: Diese Direktive wird verwendet, um anzugeben, dass derdb-Dienst demapp-networkbeitreten soll, das wir im weiteren Verlauf des Tutorials definieren werden.
Als Nächstes definieren wir die Dienstkonfiguration für unsere WordPress-Anwendung. Wir nennen den Dienst und container_name app. Fügen Sie das folgende Code-Snippet unter der db-Dienstdefinition ein und achten Sie dabei auf die richtige Einrückung:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#WordPress-Anwendungscode-Dienst app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network |
Genau wie beim db-Dienst haben wir unseren Container benannt und die Restart-Richtlinie definiert. Einige weitere Optionen, die wir hinzugefügt haben, sind unten definiert:
depends_on: Diese Direktive stellt sicher, dass Container in der Reihenfolge ihrer Abhängigkeit gestartet werden. In unserem Fall hängt derapp-Container vomdb-Container ab. Daher startet er, nachdem derdb-Container gestartet wurde. Dies muss in dieser Reihenfolge geschehen, da die WordPress-App für ihre Funktion auf die Verfügbarkeit einer MySQL-Datenbank angewiesen ist.image: Wie im Code-Snippet zu sehen ist, verwenden wir das WordPress-Version 5.1.1 fpm alpine-Image. Wir hatten bereits denphp-fpm-Prozessor erklärt, den Nginx für die PHP-Verarbeitung benötigt. Dieses Image kümmert sich darum. Das Alpine-Image, das auf dem Alpine Linux-Projekt basiert, hilft dabei, die Image-Größe geringer zu halten. Wenn Sie weitere Informationen zu Image-Varianten benötigen, können Sie diesem Link zu Docker Hub WordPress-Images.env_file: Spezifiziert den Speicherort der.env-Datei, die die Datenbank-Anmeldedaten enthält.environment: Diese Direktive definiert zusätzliche Umgebungsvariablen. In unserem Fall definieren wir die Variablen, die WordPress erwartet, und weisen ihnen die Werte der Variablen aus unserer.env-Datei zu. Dies sindWORDPRESS_DB_USER,WORDPRESS_DB_PASSWORDundWORDPRESS_DB_HOST, was sich auf den MySQL-Server bezieht, der imdb-Container läuft und über den MySQL-Standardport erreichbar ist3306. Schließlich sehen SieWORDPRESS_DB_NAME, das wir auf WordPress gesetzt haben. Derselbe Wert ist in der MySQL-Dienstdefinition im db-Container angegeben:MYSQL_DATABASE=wordpress.volumes: Diese Direktive bindet ein Volume namens app in den Mount-Pfad/var/www/htmlein, der vom WordPress-Image erstellt wurde. Die Benennung von Volumes ermöglicht die gemeinsame Nutzung von Anwendungscode mit anderen Containern.networks: Schließlich fügen wir den app-Container demapp-networkhinzu, um sicherzustellen, dass er mit anderen Containern im Netzwerk kommuniziert.
Das ist alles für den app-Dienstcontainer für das WordPress-Image. Definieren wir nun den webserver-Dienst für das Nginx-Image. Fügen Sie zuerst das folgende Code-Snippet unter der app-Dienstdefinition in Ihrer docker-compose.yml-Datei hinzu:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#Webserver Nginx-Dienst webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network |
Wir haben bereits die Option depends_on erklärt. Im Fall dieses webserver-Dienstes startet der Container, nachdem der app-Container gestartet wurde. Der Webserver-Container basiert auf dem alpine Nginx-Image. Er hat eine ähnliche Restart-Richtlinie wie die vorherigen Dienstdefinitionen. Die anderen Optionen in der webserver-Dienstdefinition umfassen:
ports: bindet die Ports zwischen dem Host-Rechner und dem Container. In Schritt 1, hatten wir den Port80in dernginx.conf-Datei definiert. Dieser Port ist dem Port80auf dem Container zugeordnet.volumes: Wir haben eine Kombination aus Bind Mounts und benannten Volumes unter dieser Option:app:/var/www/html: Diese Volume-Definition bindet die WordPress-Anwendung in das Verzeichnis/var/www/htmlein, das wir zuvor im Nginx-Server-Block als Root festgelegt hatten../nginx-conf:/etc/nginx/conf.d: Diese Definition bindet das Nginx-Konfigurationsverzeichnis auf dem Host-Rechner per Bind Mount in das für den Container definierte Nginx-Konfigurationsverzeichnis ein. Daher werden alle Änderungen auf dem Host-Rechner automatisch im Container übernommen.certbot-etc:/etc/letsencrypt: Diese Definition bindet die Let’s Encrypt-Zertifikate und -Schlüssel für die Domain in das entsprechende Verzeichnis auf dem Container ein.
networks: Wie in den vorherigen Dienstdefinitionen fügt dienetworks-Anweisung den Webserver-Dienst zuapp-networks.
Da wir mit der Webserver-Definition fertig sind, fügen wir nun Anweisungen für den Certbot-Dienst hinzu. Dieser kümmert sich darum, Ihre TLS/SSL-Zertifikate von Let’s Encrypt zu beziehen. Wenn Sie mehr über die Absicherung eines Nginx-Servers erfahren möchten, ist dieses Tutorial über wie man Nginx mit Let’s Encrypt absichert eine gute Quelle.
Fügen Sie als Nächstes das folgende Code-Snippet unter dem Webserver-Dienst hinzu. Denken Sie daran, Ihren korrekten Domainnamen und Ihre E-Mail-Adresse anzugeben:
|
1 2 3 4 5 6 7 8 9 10 |
#Certbot-Dienst certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com |
Das certbot-Image startet erst, nachdem der webserver gestartet wurde, aufgrund der depends_on-Anweisung. Docker Compose wird das Certbot-Image von Docker Hub herunterladen, wie definiert.
Unter der Volumes-Definition teilt der Certbot-Container die Domain-Zertifikate und den Schlüssel in certbot-etc mit dem Nginx-webserver-Container und den Anwendungscode mit dem app-Container.
Unter der command-Definition haben wir einen Unterbefehl angegeben, um den standardmäßigen Certbot-certonly-Befehl des Containers mit den unten aufgeführten zusätzlichen Optionen auszuführen:
-
--webroot: Spezifiziert die Verwendung des Webroot-Plugins, das Dateien zur Authentifizierung im Webroot-Ordner ablegt.--webroot-path: Spezifiziert den Pfad des Webroot-Verzeichnisses.--agree-tos: Spezifiziert, dass Sie den Nutzungsbedingungen von ACME zustimmen.--no-eff-email: Spezifiziert, dass Sie Ihre E-Mail-Adresse nicht mit der EFF teilen möchten. Sie können dies weglassen, wenn Sie sie teilen möchten.--staging: Teilt Certbot mit, dass Sie zuerst Testzertifikate aus der Staging-Umgebung von Let’s Encrypt erhalten möchten, um Ihre Konfiguration zu testen, bevor Sie das eigentliche Zertifikat anfordern. Let’s Encrypt hat eine Ratenbegrenzung für Domain-Anfragen. Daher hilft Ihnen das vorherige Testen Ihrer Konfiguration zu vermeiden, dass Ihre Domain eingeschränkt wird.-d: Diese Option übernimmt die Domainnamen für die Zertifikatsanfrage. In diesem Tutorial haben wirexample.comundwww.example.comaufgenommen. Bitte geben Sie Ihre tatsächlich registrierte Domain an.
Unsere docker-compose.yml-Datei ist fast vollständig. Sie müssen jedoch auch die Netzwerk- und Volume-Definitionen unter dem Certbot-Dienst hinzufügen:
|
1 2 3 4 5 6 7 8 9 10 |
#Volumes volumes: certbot-etc: app: dbdata: #Netzwerke networks: app-network: driver: bridge |
Der volumes-Schlüssel definiert die Volumes, die mit allen in dieser Compose-Datei definierten Diensten (Containern) geteilt werden sollen: certbot-etc, app und dbdata. Die Inhalte der Volumes, die Docker erstellt, werden in einem von Docker verwalteten Verzeichnis auf dem Host-Dateisystem gespeichert: /var/lib/docker/volumes/. Die Inhalte jedes Volumes werden dann in jedem Container gemountet, der das Volume verwendet. Dies ermöglicht es, Daten und Code zwischen Containern zu teilen.
Der networks-Schlüssel definiert das Bridge-Netzwerk, das die Kommunikation zwischen Containern ermöglicht. Container im selben Bridge-Netzwerk wie webserver und db können sicher über Ports kommunizieren, ohne den Datenverkehr für das externe Netzwerk freizugeben. Wir geben nur den Port 80 frei, um den Zugriff auf die Front-End-Webseiten zu ermöglichen.
Die vollständige docker-compose.yml-Datei wird wie folgt aussehen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
version: '3' services: #MySQL-Dienst db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network #WordPress-Anwendungscode-Dienst app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network #Webserver-Nginx-Dienst webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network #certbot-Dienst certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com #Volumes volumes: certbot-etc: app: dbdata: #Netzwerke networks: app-network: driver: bridge |
Sie können die Datei speichern und schließen. Im nächsten Schritt werden wir den Container starten und testen sowie die Zertifikatsanfragen durchführen.
Schritt 4: Ausführen der Container und Beziehen von SSL-Zertifikaten
Der größte Vorteil von Docker Compose besteht darin, dass Sie, sobald Sie alle Ihre Dienste in der docker-compose.yml-Datei können Sie alle Container mit nur einem Befehl starten: docker-compose up. Der Befehl führt jede angegebene Anweisung aus. Wenn die Domain-Anfragen erfolgreich sind, sollten Sie den korrekten Exit-Status in Ihrem Terminal sehen können. Geben Sie den folgenden Befehl ein, um die Container zu erstellen. Das -d-Flag dient dazu, die Container im Hintergrund auszuführen:
|
1 |
docker-compose up -d |
Wenn Sie die Ausgabe wie im folgenden Screenshot sehen, wurden die Dienste erfolgreich erstellt:
Um den Status der Dienste zu überprüfen, führen Sie den Befehl docker-compose ps aus:
|
1 |
docker-compose ps |
Die Ausgabe des Befehls sieht wie unten dargestellt aus, wenn alles erfolgreich war. Der Zustand der Container app, db, und webserver sollte up sein, und der certbot-Container sollte den Status Exit0 haben:
Wenn Sie etwas anderes als Up in der Statusspalte für app, db oder webserver, oder einen Exit-Status sehen, der nicht 0 für den certbot-Container ist, ist etwas schiefgelaufen. Sie können die Protokolle jedes Containers mit dem Befehl docker-compose logs überprüfen und den service_name:
|
1 |
docker-compose logs service_name |
Sie können beispielsweise die Protokolle des certbot-Containers überprüfen, indem Sie den folgenden Befehl eingeben:
|
1 |
docker-compose logs certbot |
Um zu überprüfen, ob die Zertifikate im webserver-Container gemountet wurden, verwenden Sie den Befehl docker-compose exec:
|
1 |
docker-compose exec webserver ls -la /etc/letsencrypt/live |
Wenn Sie einen tatsächlich registrierten Domainnamen anstelle von example.com verwendet haben und die Zertifikatsanfragen erfolgreich waren, sollten Sie eine Ausgabe wie diese sehen:
Sobald Sie bestätigt haben, dass die Zertifikatsanfrage erfolgreich war, können Sie die Datei docker-compose.yml bearbeiten und das --staging-Flag entfernen. Öffnen Sie die Datei mit nano:
|
1 |
nano docker-compose.yml |
Scrollen Sie nach unten zum Abschnitt der Certbot-Dienstdefinition in der Option „command“ und ersetzen Sie das --staging-Flag durch das --force-renewal-Flag. Dies teilt Certbot mit, dass Sie eine Zertifikatsverlängerung für ein Zertifikat derselben Domain anfordern. Ihre Certbot-Dienstdefinition sollte nun wie folgt aussehen:
|
1 2 3 4 5 6 7 8 9 10 |
#certbot service certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com |
Speichern Sie die Datei, wenn Sie mit der Bearbeitung fertig sind.
Geben Sie den folgenden Befehl ein, um den certbot-Container neu zu erstellen. Das enthaltene --no-deps-Flag weist Compose an, den Neustart des Webserver-Dienstes zu überspringen, da dieser bereits ausgeführt wird:
|
1 |
docker-compose up --force-recreate --no-deps Certbot |
Der Befehl gibt den folgenden Screenshot aus, der zeigt, dass die Zertifikatsanfrage erfolgreich war:
Das ist alles für diesen Schritt. Im nächsten Schritt ändern Sie die Nginx-Konfigurationsdatei, um das SSL-Zertifikat einzubinden.
Schritt 5: Aktivieren von SSL in der Nginx-Konfiguration und Dienstdefinition
Damit Nginx den Datenverkehr über sicheres SSL abwickelt, ändern Sie zunächst die Nginx-Konfigurationsdatei, um eine HTTP-Weiterleitung zu HTTPS hinzuzufügen. Anschließend müssen Sie die Speicherorte für Zertifikat und Schlüssel angeben und schließlich Sicherheitsparameter und Header hinzufügen.
Bevor Sie die Konfigurationsdatei ändern, sollten Sie die empfohlenen Nginx-Sicherheitsparameter aus dem GitHub-Repository von Certbot mit curl und dem folgenden Befehl abrufen:
|
1 |
curl -sSLo nginx-conf/options-ssl-nginx.conf |
Der Befehl wird ausgeführt und speichert die abgerufenen Parameter in einer Datei namens options-ssl-nginx.conf, im Verzeichnis nginx-conf. Entfernen Sie die Nginx-Konfigurationsdatei, damit wir mit den folgenden Befehlen eine neue erstellen können:
|
1 2 |
rm nginx-conf/nginx.conf nano nginx-conf/nginx.conf |
In der nun leeren Datei nginx.conf fügen Sie den folgenden Code hinzu, der eine Weiterleitung von HTTP auf HTTPS, SSL-Anmeldedatenprotokolle und Sicherheits-Header enthält. Ersetzen Sie, wie bereits zuvor, die Domäne example.com durch Ihre eigene registrierte Domäne:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
server { listen 80; listen [::]:80; server_name example.com www.example.com; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { rewrite ^ https://$host$request_uri? permanent; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com; index index.php index.html index.htm; root /var/www/html; server_tokens off; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; include /etc/nginx/conf.d/options-ssl-nginx.conf; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Sicherheit-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; # Aktivieren Sie Strict Transport Security nur, wenn Sie die Auswirkungen verstehen location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } } |
Im ersten Server-Block, der ungesicherte Anfragen über den Port 80 verarbeitet, geben wir das Webroot für Certbot-Erneuerungsanfragen an. Wir fügen auch eine Redirect-Direktive hinzu, die HTTP-Anfragen an HTTPS.
Der zweite Server-Block verarbeitet sicheren HTTPS-Verkehr, der über den Port 443 eingeht. Wie Sie sehen können, aktivieren wir auch SSL und HTTP2. HTTP/2 verbessert die Leistung Ihres Servers. Mehr darüber erfahren Sie in der offiziellen Nginx-Dokumentation zu HTTP/2.
In diesem Block haben wir auch festgelegt, dass Nginx die Speicherorte für das SSL-Zertifikat und den Schlüssel sowie die empfohlenen Certbot-Sicherheitsparameter enthält, die curl im Verzeichnis nginx-conf/options-ssl-nginx.conf gespeichert hat.
Die zusätzlichen Sicherheits-Header dienen dazu, die Bewertungen Ihrer Website auf Sicherheits-Testseiten wie Security Headers und SSL Labs. Sie können den Links in diesen Headern folgen, um mehr zu erfahren: X-Frame-Options, Referrer Policy, X-Content-Type-Options, X-XSS-Protection, Content-Security-Policy. Wir haben den HTTP Strict Transport Security-Header (HSTS) auskommentiert. Es steht Ihnen frei, sich über dessen Preload-Funktionalität zu informieren und zu entscheiden, ob Sie diese aktivieren möchten.
Die restlichen Direktiven wie root, index, WordPress-spezifische Location-Blöcke bleiben wie in Schritt 1 besprochen. Sie können die Datei nun speichern und schließen, wenn Sie mit der Bearbeitung fertig sind.
Nachdem wir nun den HTTPS-Verkehr über den Port 443, aktiviert haben, müssen wir diesen Port auch in der Dienstdefinition des Webservers freigeben. Geben Sie den folgenden Befehl ein, um die Datei docker-compose.yml mit nano zu öffnen:
|
1 |
nano docker-compose.yml |
Fügen Sie im Abschnitt des Webservers unter der Option „ports“ eine Zuordnung für Port 443 hinzu, wie unten hervorgehoben:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" - "443:443" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network |
Die vollständige docker-compose.yml-Datei sollte nun wie folgt aussehen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
version: '3' services: #MySQL-Dienst db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network #WordPress-Anwendungscode-Dienst app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network #Webserver-Nginx-Dienst webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" - "443:443" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network #Certbot-Dienst certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com #Volumes volumes: certbot-etc: app: dbdata: #Netzwerke networks: app-network: driver: bridge |
Sobald Sie bestätigt haben, dass alles korrekt aussieht, speichern und schließen Sie die Datei. Führen Sie danach den folgenden Befehl aus, um den webserver-Dienst neu zu erstellen:
|
1 |
docker-compose up -d --force-recreate --no-deps webserver |
|
1 |
docker-compose ps |
Da nun alle Ihre Container ausgeführt werden, können Sie mit der WordPress-Konfiguration über die Weboberfläche fortfahren.
Schritt 6: Schließen Sie Ihre WordPress-Konfiguration über die Weboberfläche ab
Navigieren Sie zum Domainnamen Ihres Servers, um die Installation fortzusetzen. Sie sollten die WordPress-Einrichtungs-Homepage sehen. Sie lädt Sie ein, Ihre Sprache auszuwählen, bevor Sie fortfahren:
Wählen Sie Ihre Sprache und klicken Sie auf Weiter, um zur nächsten Seite zu gelangen:
Tragen Sie auf dieser Seite Ihren Website-Titel ein, wählen Sie einen einprägsamen Benutzernamen und ein starkes Passwort. Aus Sicherheitsgründen wird empfohlen, nicht Admin als Benutzernamen zu verwenden. Geben Sie Ihre E-Mail-Adresse ein und klicken Sie auf die Schaltfläche WordPress installieren, um mit der Installation von WordPress zu beginnen.
Sobald die Installation abgeschlossen ist, werden Sie zum Anmeldebildschirm weitergeleitet, wo Sie den von Ihnen festgelegten Benutzernamen und das Passwort eingeben. Wenn Sie die gültigen Anmeldedaten eingeben, sollten Sie Ihr WordPress-Dashboard sehen können:
Sie haben WordPress nun erfolgreich installiert! Als Nächstes müssen Sie die Schritte unternehmen, um sicherzustellen, dass sich die SSL-Zertifikate automatisch verlängern.
Schritt 7: Konfigurieren der automatischen SSL-Zertifikatsverlängerung
TLS/SSL-Zertifikate von Let’s Encrypt sind nur 90 Tage lang gültig. Es liegt an Ihnen, eine Konfiguration für die automatische Verlängerung zu erstellen, um sicherzustellen, dass sie nicht ablaufen. Sie können dies erreichen, indem Sie ein Skript erstellen und es mit dem Dienstprogramm cron job planen. In diesem Schritt zeigen wir Ihnen, wie Sie ein Skript erstellen, das die Zertifikate verlängert. Wir werden es dann mit dem Cron-Job-Dienstprogramm planen, um es regelmäßig auszuführen und die Zertifikate zu verlängern, wenn sie sich dem Ablaufdatum nähern.
Öffnen Sie im Projektverzeichnis wordpress_docker ein Skript namens ssl_renewer.sh mit nano:
|
1 |
nano ssl_renewer.sh |
Fügen Sie dem Skript den folgenden Code hinzu, um die automatische Verlängerung und das Neuladen der Nginx-Konfiguration zu handhaben. Denken Sie daran, den hervorgehobenen Benutzernamen durch Ihren Nicht-Root-Benutzernamen zu ersetzen:
|
1 2 3 4 5 6 7 8 |
#!/bin/bash COMPOSE="/usr/local/bin/docker-compose –ansi never" DOCKER="/usr/bin/docker" cd /home/hackins/wordpress_docker/ $COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af |
In diesem Skript weisen wir die Binärdatei docker-compose einer Variablen namens COMPOSE zu. Wir fügen auch die Option –ansi never hinzu, die das Skript anweist, docker-compose-Befehle ohne ANSI-Steuerzeichen auszuführen. Weiterhin weisen wir die Docker-Binärdatei einer Variablen namens DOCKER.
zu. Das Skript wechselt dann in unser Projektverzeichnis wordpress_docker und führt die folgenden Befehle aus:
docker-compose run: Es startet den Certbot-Container und überschreibt den Befehl, den wir in der Certbot-Dienstdefinition angegeben hatten. Anstatt des Subbefehls certonly wird der Subbefehl renew ausgeführt, der die SSL/TLS-Zertifikate von Let’s Encrypt verlängert, wenn sie kurz vor dem Ablauf stehen.docker-compose kill: sendet ein SIGHUP-Signal an denwebserver-Container, um die Nginx-Konfigurationen neu zu laden. Vielleicht möchten Sie sich dieses Tutorial von Docker ansehen über wie man das offizielle Nginx-Docker-Image verwendet.docker system prune: Dieser Befehl entfernt alle ungenutzten Container und Images.
Speichern und schließen Sie die Datei, wenn Sie mit der Bearbeitung fertig sind. Führen Sie dann den folgenden Befehl aus, um sie ausführbar zu machen:
|
1 |
chmod +x ssl_renewer.sh |
Sobald Sie sie ausführbar gemacht haben, öffnen Sie Ihre Root-crontab-Datei, um das Skript regelmäßig in den von uns angegebenen Intervallen auszuführen:
|
1 |
sudo crontab -e |
Die crontab bittet Sie, Ihren bevorzugten Editor auszuwählen, wenn Sie sie zum ersten Mal verwenden:
Wählen Sie Ihren bevorzugten Editor und drücken Sie Enter, um die Datei zu öffnen. Fügen Sie am Ende der Datei die folgende Zeile hinzu:
|
1 |
*/5 * * * * /home/hackins/wordpress_docker/ssl_renewer.sh >> /var/log/cron_docker.log 2>&1 |
Dies legt das Intervall auf fünf Minuten fest, damit wir testen können, ob unser Verlängerungsskript funktioniert oder nicht. Wir haben auch eine Protokolldatei angegeben, die die Ausgabe des Jobs enthalten wird: cron_docker.log.
Warten Sie fünf Minuten und überprüfen Sie die cron.log , um zu sehen, ob das Skript mit der Erneuerungsanfrage erfolgreich war:
|
1 |
tail -f /var/log/cron_docker.log |
Sie sollten etwas Ähnliches wie auf dem folgenden Screenshot sehen, wenn die Anfragen erfolgreich waren:
Nachdem wir nun getestet und bestätigt haben, dass es funktioniert, können Sie die crontab-Datei ändern, um eine tägliche Erneuerung festzulegen. Beispielsweise möchten Sie vielleicht festlegen, dass das Skript jeden Tag um 18:00 Uhr ausgeführt wird. Ändern Sie dazu die letzte Zeile der crontab, sodass sie wie folgt aussieht:
|
1 |
0 18 * * * /home/hackins/wordpress_docker/ssl_renewer.sh >> /var/log/cron_docker.log 2>&1 |
Zusätzlich müssen Sie das Flag –dry-run aus dem Skript ssl_renewer.sh entfernen, um sicherzustellen, dass die tatsächliche Erneuerung stattfindet, wenn es ausgeführt wird. Es sollte wie folgt aussehen:
|
1 2 3 4 5 6 7 8 |
#!/bin/bash COMPOSE="/usr/local/bin/docker-compose --ansi never" DOCKER="/usr/bin/docker" cd /home/hackins/wordpress_docker/ $COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af |
Speichern und schließen Sie als Nächstes die Datei. Danach wird der Cron-Job Ihre Zertifikate gültig halten, indem er sie vor Ablauf der 90 Tage erneuert.
Fazit
Wenn Sie es in diesem Tutorial so weit geschafft haben, können Sie sich als einen Schritt näher an der Rolle eines DevOps-Engineers betrachten. Sie konnten ein Nginx-Konfigurationsskript erstellen, haben eine docker-compose.yml-Datei erstellt und mehrere Dienste definiert, die für die Ausführung einer WordPress-Anwendung mit Docker und Docker Compose erforderlich sind. Sie haben SSL/TLS-Zertifikate von Let’s Encrypt erhalten, um sicherzustellen, dass Ihr Webserver sicher ist. Schließlich haben Sie einen Cron-Job erstellt, um sicherzustellen, dass die Zertifikate nicht ablaufen. Gute Arbeit!
Wenn Sie tiefer in DevOps einsteigen möchten, werfen Sie einen Blick auf weitere Ressourcen zu Containern in unserem Blog:
- Kubernetes kennenlernen
- Wie man eine Node.js (Express.js) App mit Docker auf Ubuntu 20.04 bereitstellt
- Bereitstellen einer PHP-Anwendung auf einem Kubernetes-Cluster mit Ubuntu 18.04.
- Bereitstellung von Laravel, Nginx und MySQL mit Docker Compose
Viel Spaß beim Computing!










Kommentare
Noch keine Kommentare. Schreiben Sie den ersten.