One place for hosting & domains

      Drupal

      So installieren Sie Drupal mit Docker Compose


      Der Autor hat die United Nations Foundation dazu ausgewählt, im Rahmen des Programms Write for DOnations eine Spende zu erhalten.

      Die ursprüngliche WordPress-Version dieses Tutorials wurde von Kathleen Juell verfasst.

      Einführung

      Drupal ist ein Content-Management-System (CMS), das in PHP geschrieben und unter der Open-Source-Lizenz GNU General Public License vergeben wird. Menschen und Organisationen in der ganzen Welt verwenden Drupal, um öffentliche Websites, persönliche Blogs, Unternehmen und mehr zu betreiben. Was Drupal von anderen CMS-Frameworks abhebt, ist seine wachsende Community und eine Reihe von Funktionen, die sichere Prozesse, zuverlässige Leistung, Modularität und Flexibilität zur Anpassung umfassen.

      Drupal erfordert die Installation des LAMP-Stacks (Linux, Apache, MySQL und PHP) oder des LEMP-Stacks (Linux, Nginx, MySQL und PHP), aber das Installieren einzelner Komponenten ist eine zeitaufwendige Aufgabe. Wir können Tools wie Docker und Docker Compose verwenden, um den Prozess der Installation von Drupal zu vereinfachen. Dieses Tutorial verwendet Docker-Images zur Installation einzelner Komponenten in den Docker-Containern. Mit der Verwendung von Docker Compose können wir mehrere Container für die Datenbank, die Anwendung und für die Vernetzung/Kommunikation zwischen ihnen definieren und verwalten.

      In diesem Tutorial installieren wir Drupal mit Docker Compose, damit wir die Containerisierung nutzen und unsere Drupal-Website auf Servern bereitstellen können. Wir führen Container für eine MySQL-Datenbank, einen Nginx-Webserver und Drupal aus. Außerdem sichern wir unsere Installation, indem wir TLS/SSL Zertifikate mit Let’s Encrypt für die Domäne erlangen, die wir mit unserer Website verknüpfen möchten. Schließlich richten wir einen cron-Job ein, um unsere Zertifikate zu erneuern, damit unsere Domäne sicher bleibt.

      Voraussetzungen

      Um diesem Tutorial zu folgen, benötigen Sie:

      • Einen Server, auf dem Ubuntu 18.04 ausgeführt wird, zusammen mit einem non-root user mit sudo-Privilegien und einer aktiven Firewall. Eine Anleitung für das Setup finden Sie im Leitfaden für die Ersteinrichtung des Servers.
      • Docker, gemäß Schritt 1 und 2 unter So installieren und verwenden Sie Docker unter Ubuntu 18.04 auf Ihrem Server installiert. Dieses Tutorial wurde unter der Version 19.03.8 getestet.
      • Docker Compose, gemäß Schritt 1 unter So installieren Sie Compose unter Ubuntu 18.04 auf Ihrem Server installiert. Dieses Tutorial wurde unter der Version 1.21.2 getestet.
      • Einen registrierten Domänennamen. Dieses Tutorial verwendet in allen Bereichen your_domain. Einen Domänennamen können Sie kostenlos bei Freenom erhalten oder Sie nutzen eine Domänenregistrierungsstelle Ihrer Wahl.
      • Die beiden folgenden DNS-Einträge für Ihren Server eingerichtet. Falls Sie ein DigitalOcean-Konto nutzen, können Sie in der Einführung in DigitalOcean-DNS im Einzelnen nachlesen, wie Sie diese hinzufügen:
        • Einen A-Eintrag mit your_domain, der auf die öffentliche IP-Adresse Ihres Servers verweist.
        • Einen A-Eintrag mit www.your_domain, der auf die öffentliche IP-Adresse Ihres Servers verweist.

      Schritt 1 — Definieren der Webserver-Konfiguration

      Bevor wir Container ausführen, müssen wir die Konfiguration für unseren Nginx-Webserver definieren. Unsere Konfigurationsdatei enthält einige Drupal-spezifische Location-Blocks, zusammen mit einem Location-Block zur Weiterleitung von Verifizierungsanforderungen von Let’s Encrypt an den Certbot-Client für automatisierte Zertifikatserneuerungen.

      Zuerst erstellen wir ein Projektverzeichnis für unser Drupal-Setup namens drupal:

      Rufen Sie das neu erstellte Verzeichnis auf:

      Nun können wir ein Verzeichnis für unsere Konfigurationsdatei erstellen:

      Öffnen Sie die Datei mit nano oder Ihrem bevorzugten Texteditor:

      • nano nginx-conf/nginx.conf

      In dieser Datei fügen wir einen Serverblock mit Anweisungen für unseren Servernamen und die Dokumenten-root hinzu sowie Location-Blocks, um die Anforderung des Certbot-Clients nach Zertifikaten, PHP-Verarbeitung und statischen Asset-Anforderungen zu leiten.

      Fügen Sie den folgenden Code in die Datei ein. Achten Sie darauf, your_domain durch Ihren eigenen Domänennamen zu ersetzen:

      ~/drupal/nginx-conf/nginx.conf

      server {
          listen 80;
          listen [::]:80;
      
          server_name your_domain www.your_domain;
      
          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;
          }
      
          rewrite ^/core/authorize.php/core/authorize.php(.*)$ /core/authorize.php$1;
      
          location ~ .php$ {
              try_files $uri =404;
              fastcgi_split_path_info ^(.+.php)(/.+)$;
              fastcgi_pass drupal: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;
          }
      }
      

      Unser Serverblock enthält folgende Informationen:

      Anweisungen:

      • listen: Diese weist Nginx an, an Port 80 zu lauschen, sodass wir das Webroot-Plugin von Certbot für unsere Zertifikatsanforderungen nutzen können. Beachten Sie, dass wir noch nicht Port 443 einschließen – wir aktualisieren unsere Konfiguration, um SSL einzuschließen, sobald wir erfolgreich unsere Zertifikate erlangt haben.

      • server_name: Damit definieren Sie den Servernamen und den Serverblock, der für Anfragen an den Server verwendet werden sollte. Achten Sie darauf, your_domain in dieser Zeile durch Ihren eigenen Domänennamen zu ersetzen.

      • index: Die Anweisung index definiert die Dateien, die als Indizes bei der Verarbeitung von Anfragen an unseren Server dienen. Wir haben hier die Standardreihenfolge der Priorität geändert und index.php vor index.html geschoben, damit Nginx Dateien namens index.php wenn möglich priorisiert.

      • root: Unsere root-Anweisung benennt das root-Verzeichnis für Anfragen an unseren Server. Dieses Verzeichnis, /var/www/html, wird als Bereitstellungspunkt in der Erstellungszeit durch Anweisungen in unserer Drupal Dockerfile erstellt. Diese Dockerfile-Anweisungen stellen auch sicher, dass die Dateien aus der Drupal-Version auf diesem Volume bereitgestellt werden.

      • rewrite: Wenn die angegebene reguläre Expression (^/core/authorize.php/core/authorize.php(.*)$) mit einer URI-Anfrage übereinstimmt, wird die URI wie in der Ersatzzeichenfolge (/core/authorize.php$1) angegeben geändert.

      Location-Blocks:

      • location ~ /.well-known/acme-challenge: Dieser Location-Block verwaltet Anfragen an das Verzeichnis .well-known, in dem Certbot eine temporäre Datei ablegt, um zu validieren, dass das DNS für unsere Domäne auf unserem Server aufgelöst wird. Mit dieser Konfiguration können wir das Webroot-Plugin von Certbot verwenden, um Zertifikate für unsere Domäne zu erlangen.

      • location /: In diesem Location-Block verwenden wir eine try_files-Anweisung, um nach Dateien zu suchen, die individuellen URI-Anfragen entsprechen. Anstatt jedoch einen 404 Not Found-Status auszugeben, übergeben wir die Steuerung an die Datei index.php von Drupal mit den Anforderungsargumenten.

      • location ~ .php$: Dieser Location-Block verwaltet die PHP-Verarbeitung und überträgt diese Anfragen an unseren drupal-Container. Da unser Drupal-Docker-Image auf dem php:fpm-Image basiert, schließen wir auch Konfigurationsoptionen ein, die in diesem Block für das FastCGI-Protokoll spezifisch sind. Nginx erfordert einen unabhängigen PHP-Prozessor für PHP-Anfragen: In unserem Fall werden diese Anfragen vom php-fpm-Prozessor verwaltet, der im php:fpm-Image enthalten ist. Außerdem enthält dieser Location-Block FastCGI-spezifische Anweisungen, Variablen und Optionen, die Anfragen an die in unserem Drupal-Container ausgeführte Drupal-Anwendung überträgt, den bevorzugten Index für die analysierte Anfrage-URI festlegt und URI-Anfragen analysiert.

      • location ~ /.ht: Dieser Block verwaltet .htaccess-Dateien, da Nginx diese nicht bedient. Die Anweisung deny_all stellt sicher, dass .htaccess-Dateien nie für Benutzer bereitgestellt werden.

      • location = /favicon.ico, location = /robots.txt: Diese Blocks stellen sicher, dass Anfragen an /favicon.ico und /robots.txt nicht protokolliert werden.

      • location ~* . (css|gif|ico|jpeg|jpg|js|png)$: Dieser Block schaltet die Protokollierung für statische Asset-Anfragen ab und stellt sicher, dass diese Assets in hohem Maße zwischenspeicherbar sind, da ihre Bereitstellung in der Regel aufwendig ist.

      Weitere Informationen zu FastCGI-Proxying finden Sie in Verstehen und Implementieren von FastCGI-Proxying in Nginx. Informationen zu Server- und Location-Blocks finden Sie in Verstehen von Nginx-Server- und Location-Block-Auswahlalgorithmen.

      Wenn die Bearbeitung abgeschlossen wurde, speichern und schließen Sie die Datei.

      Nach Einrichtung der Nginx-Konfiguration können Sie Umgebungsvariablen erstellen, die zur Laufzeit an Ihre Anwendungs- und Datenbankcontainer übergeben werden.

      Schritt 2 — Definieren der Umgebungsvariablen

      Unsere Drupal-Anwendung benötigt eine Datenbank (MySQL, PostgresSQL, etc.) zum Speichern von Informationen im Zusammenhang mit der Website. Der Drupal-Container benötigt Zugriff auf bestimmte Umgebungsvariablen zur Laufzeit, um Zugriff auf den Datenbank-Container (MySQL) zu ermöglichen. Diese Variablen enthalten sensible Informationen wie die Zugangsdaten der Datenbank, sodass wir sie nicht direkt in der Docker-Compose-Datei offenlegen können – der Hauptdatei, die Informationen darüber enthält, wie unsere Container ausgeführt werden.

      Es wird immer empfohlen, die sensiblen Werte in der .env-Datei festzulegen und ihre Zirkulation zu beschränken. Dadurch werden diese Werte nicht in unsere Projekt-Repositorys kopiert und öffentlich verfügbar gemacht.

      Erstellen und öffnen Sie im Haupt-Projektverzeichnis ~/drupal eine Datei namens .env:

      Fügen Sie die folgenden Variablen in die .env-Datei ein und ersetzen Sie dabei die hervorgehobenen Abschnitte mit den Zugangsdaten, die Sie verwenden möchten:

      ~/drupal/.env

      MYSQL_ROOT_PASSWORD=root_password
      MYSQL_DATABASE=drupal
      MYSQL_USER=drupal_database_user
      MYSQL_PASSWORD=drupal_database_password
      

      Wir haben nun das Passwort für das MySQL-root-Administratorkonto sowie unseren bevorzugten Benutzernamen und das Passwort für unsere Anwendungsdatenbank hinzugefügt.

      Unsere .env-Datei enthält sensible Informationen. Es wird daher immer empfohlen, sie in die .gitignore– und .dockerignore-Dateien des Projekts einzufügen, damit sie nicht in unseren Git-Repositorys und Docker-Images hinzugefügt werden.

      Wenn Sie mit Git zur Versionskontrolle arbeiten möchten, initialisieren Sie Ihr aktuelles Arbeitsverzeichnis als ein Repository mit git init:

      Öffnen Sie die .gitignore-Datei:

      Fügen Sie Folgendes hinzu:

      ~/drupal/.gitignore

      .env
      

      Speichern und schließen Sie die Datei.

      Öffnen Sie in ähnlicher Weise die .dockerignore-Datei:

      Fügen Sie Folgendes hinzu:

      ~/drupal/.dockerignore

      .env
      .git
      

      Speichern und schließen Sie die Datei.

      Wir haben nun die Maßnahmen zur Sicherung unserer Zugangsdaten als Umgebungsvariablen ergriffen. Im nächsten Schritt definieren wir unsere Dienste in einer docker-compose.yml-Datei.

      Schritt 3 — Definieren der Dienste mit Docker Compose

      Docker Compose ist ein Tool zum Definieren und Ausführen von Docker-Anwendungen mit mehreren Containern. Wir definieren eine YAML-Datei, um die Dienste unserer Anwendung zu konfigurieren. Ein Dienst oder service in Docker Compose ist ein Container, der ausgeführt wird. Compose ermöglicht uns, diese Dienste zusammen mit geteilten Volumes und Netzwerken zu verknüpfen.

      Wir erstellen verschiedene Container für die Drupal-Anwendung, die Datenbank und den Webserver. Außerdem erstellen wir einen Container, der Certbot ausführt, um Zertifikate für unseren Webserver zu erlangen.

      Erstellen Sie eine docker-compose.yml-Datei:

      Fügen Sie den folgenden Code hinzu, um die Compose-Dateiversion und den mysql-Datenbankdienst zu definieren:

      ~/drupal/docker-compose.yml

      version: "3"
      
      services:
        mysql:
          image: mysql:8.0
          container_name: mysql
          command: --default-authentication-plugin=mysql_native_password
          restart: unless-stopped
          env_file: .env
          volumes:
            - db-data:/var/lib/mysql
          networks:
            - internal
      

      Wir behandeln diese nacheinander mit allen Konfigurationsoptionen des mysql-Dienstes:

      • image: Hiermit wird das Image festgelegt, das wir zum Erstellen des Containers verwenden/pullen. Es wird immer empfohlen, das Image mit dem richtigen Versions-Tag unter Ausschluss des latest-Tags zu verwenden, um zukünftige Konflikte zu vermeiden. Lesen Sie dazu mehr in Best Practices für Dockerfiles in der Docker-Dokumentation.

      • container_name: Hiermit wird der Name des Containers definiert.

      • command: Diese Option wird verwendet, um den Standardbefehl (CMD-Instruktion) im Image zu überschreiben. MySQL hat verschiedene Authentifizierungs-Plugins unterstützt, aber mysql_native_password ist die traditionelle Methode zur Authentifizierung. Da PHP und damit Drupal nicht die neuere MySQL-Authentifizierung unterstützen, müssen wir das --default-authentication-plugin=mysql_native_password als standardmäßigen Authentifizierungsmechanismus festlegen.

      • restart: Diese Option wird verwendet, um die Neustartregel des Containers festzulegen. Die Regel unless-stopped startet einen Container neu, bis er manuell gestoppt wird.

      • env_file: Hiermit werden die Umgebungsvariablen aus einer Datei hinzugefügt. In unserem Fall werden die Umgebungsvariablen aus der im vorherigen Schritt definierten .env-Datei gelesen.

      • volumes: Hiermit werden Host-Pfade oder benannte Volumes, die als Suboptionen eines Dienstes angegeben sind, bereitgestellt. Wir stellen ein benanntes Volume namens db-data im Verzeichnis /var/lib/mysql des Containers bereit, in der MySQL standardmäßig seine Datendateien schreibt.

      • networks: Hiermit wird das internal-Netzwerk, an das sich unser Anwendungsdienst anschließt, definiert. Wir definieren die Netzwerke am Ende der Datei.

      Wir haben unsere mysql-Dienstdefiniton definiert. Nun fügen wir die Definition des drupal-Anwendungsdienstes am Ende der Datei hinzu:

      ~/drupal/docker-compose.yml

      ...
        drupal:
          image: drupal:8.7.8-fpm-alpine
          container_name: drupal
          depends_on:
            - mysql
          restart: unless-stopped
          networks:
            - internal
            - external
          volumes:
            - drupal-data:/var/www/html
      

      In dieser Dienstdefinition benennen wir unseren Container und definieren eine Neustartregel, wie wir es beim mysql-Dienst getan haben. Außerdem fügen wir einige Optionen hinzu, die für diesen Container spezifisch sind:

      • image: Hier verwenden wir Drupal-Image 8.7.8-fpm-alpine. Dieses Image verfügt über den php-fpm-Prozessor, den unser Nginx-Webserver zur Verwaltung der PHP-Verarbeitung benötigt. Darüber hinaus verwenden wir das aus dem Alpine-Linux-Projekt erlangte alpine-Image, das die Größe des Gesamtimages reduziert und in den Best Practices für Dockerfiles empfohlen wird. Drupal verfügt über weitere Versionen von Images, die Sie auf Dockerhub finden können.

      • depends_on: Diese Option wird verwendet, um Abhängigkeit zwischen Diensten auszudrücken. Das Definieren des mysql-Dienstes als Abhängigkeit unseres drupal-Containers stellt sicher, dass unser drupal-Container nach dem mysql-Container erstellt wird und ermöglicht einen reibungslosen Start unserer Anwendung.

      • networks: Hier haben wir diesen Container zusammen mit dem internal-Netzwerk dem external-Netzwerk hinzugefügt. Dadurch wird sichergestellt, dass unser mysql-Dienst nur über das internal-Netzwerk aus dem drupal-Container zugänglich ist, während dieser Container über das external-Netzwerk für andere Container weiterhin zugänglich bleibt.

      • volumes: Wir stellen ein benanntes Volume namens drupal-data im Bereitstellungspunkt /var/www/html bereit, der vom Drupal-Image erstellt wurde. Wenn wir ein benanntes Volume auf diese Weise verwenden, können wir unseren Anwendungscode mit anderen Containern teilen.

      Als Nächstes fügen wir die Nginx-Dienstdefinition nach der drupal-Dienstdefinition hinzu:

      ~/drupal/docker-compose.yml

      ...
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      

      Auch hier benennen wir unseren Container und machen ihn in der Reihenfolge des Starts vom Drupal-Container abhängig. Außerdem verwenden wir ein alpine-Image – das Nginx-Image 1.17.4-alpine.

      Diese Dienstdefinition enthält auch die folgenden Optionen:

      • ports: Hiermit wird Port 80 zur Verfügung gestellt, um die Konfigurationsoptionen zu aktivieren, die wir in unserer Datei nginx.conf in Schritt 1 definiert haben.

      • volumes: Hier definieren wir sowohl das benannte Volume als auch den Host-Pfad:

        • drupal-data:/var/www/html: Hiermit wird unser Drupal-Anwendungscode im Verzeichnis /var/www/html, das wir als die root in unserem Nginx-Serverblock festgelegt haben, bereitgestellt.
        • ./nginx-conf:/etc/nginx/conf.d: Hiermit wird das Nginx-Konfigurationsverzeichnis auf dem Host in dem entsprechenden Verzeichnis im Container bereitgestellt. Dadurch wird sichergestellt, dass alle Änderungen, die wir an Dateien auf dem Host vornehmen, im Container reflektiert werden.
        • certbot-etc:/etc/letsencrypt: Hiermit werden die relevanten Let’s-Encrypt-Zertifikate und die Schlüssel für unsere Domäne in dem entsprechenden Verzeichnis des Containers bereitgestellt.
        • networks: Wir haben das external-Netzwerk nur definiert, damit dieser Container mit dem drupal-Container, aber nicht mit dem mysql-Container kommunizieren kann.

      Schließlich fügen wir unsere letzte Dienstdefinition für den certbot-Dienst hinzu. Achten Sie darauf, sammy@your_domain und your_domain durch Ihre eigene E-Mail-Adresse und den Domänennamen zu ersetzen:

      ~/drupal/docker-compose.yml

      ...
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
      

      Diese Definition weist Compose an, das Image certbot/certbot von Docker Hub zu pullen. Außerdem werden benannte Volumes verwendet, um Ressourcen für den Nginx-Container freizugeben, einschließlich der Domänenzertifikate und des Schlüssels in certbot-etc und des Anwendungscodes in drupal-data.

      Wir haben auch depends_on verwendet, um sicherzustellen, dass der certbot-Container gestartet wird, nachdem der webserver-Dienst ausgeführt wird.

      Wir haben hier keine networks angegeben, da dieser Container mit keinem Dienst über das Netzwerk kommunizieren wird. Es werden nur die Domänenzertifikate und der Schlüssel hinzugefügt, die wir mit den benannten Volumes bereitgestellt haben.

      Außerdem haben wir die Option command eingeschlossen, die einen Unterbefehl angibt, der mit dem Standardbefehl certbot des Containers ausgeführt werden soll. Der Certbot-Client unterstützt Plugins zur Erstellung und Installation von Zertifikaten. Wir verwenden das webroot-Plugin, um ein Zertifikat zu erlangen, indem wir certonly und --webroot in die Befehlszeile einfügen. Lesen Sie mehr über das Plugin und zusätzliche Befehle in der offiziellen Certbot-Dokumentation.

      Fügen Sie nach der certbot-Dienstdefinition die Netzwerk- und Volume-Definitionen hinzu:

      ~/drupal/docker-compose.yml

      ...
      networks:
        external:
          driver: bridge
        internal:
          driver: bridge
      
      volumes:
        drupal-data:
        db-data:
        certbot-etc:
      

      Mit dem networks-Schlüssel der obersten Ebene können wir die zu erstellenden Netzwerke angeben. networks ermöglicht die Kommunikation über die Dienste/Container auf allen Ports, da sie sich auf demselben Docker-Daemon-Host befinden. Wir haben zwei Netzwerke, internal und external, definiert, um die Kommunikation der Dienste webserver, drupal und mysql zu sichern.

      Der volumes-Schlüssel wird verwendet, um die benannten Volumes drupal-data, db-data und certbot-etc zu definieren. Wenn Docker Volumes erstellt, werden die Inhalte des Volumes in einem Verzeichnis des Host-Dateisystems, /var/lib/docker/volumes/, gespeichert, das von Docker verwaltet wird. Die Inhalte jedes Volumes werden dann von diesem Verzeichnis in jedem Container bereitgestellt, der das Volume verwendet. Auf diese Weise können Code und Daten zwischen Containern geteilt werden.

      Die fertige docker-compose.yml-Datei sieht so aus:

      ~/drupal/docker-compose.yml

      version: "3"
      
      services:
        mysql:
          image: mysql:8.0
          container_name: mysql
          command: --default-authentication-plugin=mysql_native_password
          restart: unless-stopped
          env_file: .env
          volumes:
            - db-data:/var/lib/mysql
          networks:
            - internal
      
        drupal:
          image: drupal:8.7.8-fpm-alpine
          container_name: drupal
          depends_on:
            - mysql
          restart: unless-stopped
          networks:
            - internal
            - external
          volumes:
            - drupal-data:/var/www/html
      
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
      
      networks:
        external:
          driver: bridge
        internal:
          driver: bridge
      
      volumes:
        drupal-data:
        db-data:
        certbot-etc:
      

      Nun sind unsere Dienstdefinitionen fertig. Als Nächstes starten wir den Container und testen unsere Zertifikatsanforderungen.

      Schritt 4 — Erlangen der SSL-Zertifikate und Zugangsdaten

      Wir können unsere Container mit dem Befehl docker-compose up starten, der die Container in der von uns angegebenen Reihenfolge erstellt und ausführt. Wenn unsere Domain-Anfragen erfolgreich sind, sehen wir den richtigen Exit-Status in unserer Ausgabe und die richtigen Zertifikate, die im Ordner /etc/letsencrypt/live im Webservercontainer bereitgestellt werden.

      Um die Container im Hintergrund auszuführen, verwenden Sie den Befehl docker-compose up mit dem Flag -d:

      Sie sehen eine ähnliche Ausgabe, die bestätigt, dass Ihre Dienste erstellt wurden:

      Output

      ... Creating mysql ... done Creating drupal ... done Creating webserver ... done Creating certbot ... done

      Überprüfen Sie den Status der Dienste mit dem Befehl docker-compose ps:

      Wir sehen die Dienste mysql, drupal und webserver mit einem State von Up, während certbot mit einer Statusmeldung von 0 beendet wird:

      Output

      Name Command State Ports -------------------------------------------------------------------------- certbot certbot certonly --webroot ... Exit 0 drupal docker-php-entrypoint php-fpm Up 9000/tcp mysql docker-entrypoint.sh --def ... Up 3306/tcp, 33060/tcp webserver nginx -g daemon off; Up 0.0.0.0:80->80/tcp

      Wenn Sie in der Spalte State für die Dienste mysql, drupal oder webserver etwas anderes als Up sehen, oder für den certbot-Container einen anderen Exit-Status als 0, überprüfen Sie die Dienstprotokolle mit dem Befehl docker-compose logs:

      • docker-compose logs service_name

      Wir können nun mit dem Befehl docker-compose exec überprüfen, dass unsere Zertifikate auf dem webserver bereitgestellt wurden:

      • docker-compose exec webserver ls -la /etc/letsencrypt/live

      Dadurch erhalten Sie folgende Ausgabe:

      Output

      total 16 drwx------ 3 root root 4096 Oct 5 09:15 . drwxr-xr-x 9 root root 4096 Oct 5 09:15 .. -rw-r--r-- 1 root root 740 Oct 5 09:15 README drwxr-xr-x 2 root root 4096 Oct 5 09:15 your_domain

      Nachdem nun alles erfolgreich ausgeführt wird, können wir unsere certbot-Dienstdefinition bearbeiten, um das Flag --staging zu entfernen.

      Öffnen Sie die Datei docker-compose.yml, gehen Sie zur certbot-Dienstdefinition und ersetzen Sie das Flag --staging in der Befehlsoption mit dem Flag --force-renewal, das Certbot mitteilt, dass Sie ein neues Zertifikat mit denselben Domänen wie ein vorhandenes Zertifikat anfordern möchten. Die aktualisierte Definition von certbot sieht wie folgt aus:

      ~/drupal/docker-compose.yml

      ...
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
      ...
      

      Wir müssen docker-compose erneut ausführen, um den certbot-Container neu zu erstellen. Wir schließen auch die Option --no-deps ein, um Compose mitzuteilen, dass das Starten des webserver-Dienstes übersprungen werden kann, da dieser bereits ausgeführt wird:

      • docker-compose up --force-recreate --no-deps certbot

      In der Ausgabe sehen wir, dass unsere Zertifikatsanforderung erfolgreich war:

      Output

      Recreating certbot ... done Attaching to certbot certbot | Saving debug log to /var/log/letsencrypt/letsencrypt.log certbot | Plugins selected: Authenticator webroot, Installer None certbot | Renewing an existing certificate certbot | Performing the following challenges: certbot | http-01 challenge for your_domain certbot | http-01 challenge for www.your_domain certbot | Using the webroot path /var/www/html for all unmatched domains. certbot | Waiting for verification... certbot | Cleaning up challenges certbot | IMPORTANT NOTES: certbot | - Congratulations! Your certificate and chain have been saved at: certbot | /etc/letsencrypt/live/your_domain/fullchain.pem certbot | Your key file has been saved at: certbot | /etc/letsencrypt/live/your_domain/privkey.pem certbot | Your cert will expire on 2020-01-03. To obtain a new or tweaked certbot | version of this certificate in the future, simply run certbot certbot | again. To non-interactively renew *all* of your certificates, run certbot | "certbot renew" certbot | - Your account credentials have been saved in your Certbot certbot | configuration directory at /etc/letsencrypt. You should make a certbot | secure backup of this folder now. This configuration directory will certbot | also contain certificates and private keys obtained by Certbot so certbot | making regular backups of this folder is ideal. certbot | - If you like Certbot, please consider supporting our work by: certbot | certbot | Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate certbot | Donating to EFF: https://eff.org/donate-le certbot | certbot exited with code 0

      Nachdem wir unsere Zertifikate erfolgreich generiert haben, können wir unsere Nginx-Konfiguration aktualisieren, um SSL einzuschließen.

      Schritt 5 — Ändern der Webserver-Konfiguration und Dienstdefinition

      Nach der Installation von SSL-Zertifikaten in Nginx müssen wir alle HTTP-Anfragen an HTTPS umleiten. Außerdem müssen wir unser SSL-Zertifikat und unsere Schlüsselpositionen angeben und Sicherheitsparameter sowie Header hinzufügen.

      Da Sie den webserver-Dienst neu erstellen, um diese Ergänzungen einzuschließen, können Sie diesen jetzt stoppen:

      • docker-compose stop webserver

      Dadurch erhalten Sie folgende Ausgabe:

      Output

      Stopping webserver ... done

      Als Nächstes entfernen wir die zuvor erstellte Nginx-Konfigurationsdatei:

      Öffnen Sie eine andere Version der Datei:

      • nano nginx-conf/nginx.conf

      Fügen Sie der Datei den folgenden Code hinzu, um HTTP an HTTPS umzuleiten und SSL-Zugangsdaten, Protokolle und Sicherheitsheader hinzuzufügen. Denken Sie daran, your_domain durch Ihre eigene Domäne zu ersetzen:

      ~/drupal/nginx-conf/nginx.conf

      server {
          listen 80;
          listen [::]:80;
      
          server_name your_domain www.your_domain;
      
          location ~ /.well-known/acme-challenge {
              allow all;
              root /var/www/html;
          }
      
          location / {
              rewrite ^ https://$host$request_uri? permanent;
          }
      }
      server {
          listen 443 ssl;
          listen [::]:443 ssl;
          server_name your_domain www.your_domain;
      
          index index.php index.html index.htm;
      
          root /var/www/html;
      
          server_tokens off;
      
          ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
          ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
      
          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-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
      
          location / {
              try_files $uri $uri/ /index.php$is_args$args;
          }
      
          rewrite ^/core/authorize.php/core/authorize.php(.*)$ /core/authorize.php$1;
      
          location ~ .php$ {
              try_files $uri =404;
              fastcgi_split_path_info ^(.+.php)(/.+)$;
              fastcgi_pass drupal: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;
          }
      }
      

      Der HTTP-Serverblock gibt das Webroot-Plugin für Certbot-Erneuerungsanfragen an das Verzeichnis .well-known/acme-challenge an. Er enthält auch eine rewrite-Anweisung, die HTTP-Anfragen an das root-Verzeichnis an HTTPS leitet.

      Der HTTPS-Serverblock aktiviert ssl und http2. Weitere Informationen dazu, wie HTTP/2 über HTTP-Protokolle iteriert und welche Vorteile es für die Website-Leistung haben kann, lesen Sie bitte in der Einführung Einrichten von Nginx mit HTTP/2-Support unter Ubuntu 18.04.

      Diese Blocks aktivieren SSL, da wir unser SSL-Zertifikat und die Schlüsselpositionen zusammen mit den empfohlenen Headern eingefügt haben. Diese Header ermöglichen uns eine A-Bewertung auf den Server-Testseiten SSL-Labs und Security Headers.

      Unsere Anweisungen root und index befinden sich ebenfalls in diesem Block, ebenso wie die restlichen Drupal-spezifischen Location-Blocks, die in Schritt 1 behandelt wurden.

      Speichern und schließen Sie die aktualisierte Nginx-Konfigurationsdatei.

      Bevor wir den webserver-Container neu erstellen, müssen wir unserem webserver-Dienst ein 443-Port-Mapping hinzufügen, da wir SSL-Zertifikate aktiviert haben.

      Öffnen Sie die Datei docker-compose.yml:

      Führen Sie die folgenden Änderungen in der webserver-Dienstdefinition aus:

      ~/drupal/docker-compose.yml

      ...
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
            - 443:443
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      ...
      

      Nach dem Aktivieren der SSL-Zertifikate sieht unsere docker-compose.yml wie folgt aus:

      ~/drupal/docker-compose.yml

      version: "3"
      
      services:
        mysql:
          image: mysql:8.0
          container_name: mysql
          command: --default-authentication-plugin=mysql_native_password
          restart: unless-stopped
          env_file: .env
          volumes:
            - db-data:/var/lib/mysql
          networks:
            - internal
      
        drupal:
          image: drupal:8.7.8-fpm-alpine
          container_name: drupal
          depends_on:
            - mysql
          restart: unless-stopped
          networks:
            - internal
            - external
          volumes:
            - drupal-data:/var/www/html
      
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
            - 443:443
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
      
      networks:
        external:
          driver: bridge
        internal:
          driver: bridge
      
      volumes:
        drupal-data:
        db-data:
        certbot-etc:
      

      Speichern und schließen Sie die Datei. Wir erstellen den webserver-Dienst mit unserer aktualisierten Konfiguration nun neu:

      • docker-compose up -d --force-recreate --no-deps webserver

      Dadurch erhalten Sie folgende Ausgabe:

      Output

      Recreating webserver ... done

      Überprüfen Sie die Dienste mit docker-compose ps:

      Wir sehen die Dienste mysql, drupal und webserver als Up, während certbot mit der Statusmeldung 0 beendet wird:

      Output

      Name Command State Ports -------------------------------------------------------------------------- certbot certbot certonly --webroot ... Exit 0 drupal docker-php-entrypoint php-fpm Up 9000/tcp mysql docker-entrypoint.sh --def ... Up 3306/tcp, 33060/tcp webserver nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp

      Jetzt werden alle unsere Dienste ausgeführt und wir können mit der Installation von Drupal über die Web-Oberfläche fortfahren.

      Schritt 6 – Abschließen der Installation über die Weboberfläche

      Beenden wir die Installation über die Weboberfläche von Drupal.

      Navigieren Sie in einem Webbrowser zur Domäne des Servers. Denken Sie daran, your_domain hier mit Ihrem eigenen Domänennamen zu ersetzen:

      https://your_domain
      

      Wählen Sie die Sprache aus, die Sie verwenden möchten:

      Sprachauswahlseite auf der Drupal-Weboberfläche

      Klicken Sie auf Speichern und fortfahren. Wir werden zur Seite der Installationsprofile geleitet. Drupal bietet verschiedene Profile. Wählen Sie das Profil Standard und klicken Sie auf Speichern und fortfahren.

      Profilauswahlseite auf der Drupal-Weboberfläche

      Nach Auswahl des Profils gehen wir weiter zur Seite der Datenbankkonfiguration. Wählen Sie als Datenbanktyp MySQL, MariaDB, Percona Server oder äquivalent aus. Geben Sie die Werte für Datenbankname, Benutzername und Passwort entsprechend der Werte von MYSQL_DATABASE, MYSQL_USER und MYSQL_PASSWORD ein, die jeweils in der .env-Datei in Schritt 2 definiert wurden. Klicken Sie auf Erweiterte Optionen und setzen Sie den Wert für Host auf den Namen des mysql-Dienstcontainers. Klicken Sie auf Speichern und fortfahren.

      Datenbankeinrichtungsseite auf der Drupal-Weboberfläche

      Nach Konfiguration der Datenbank beginnt die Installation der Standardmodule und Themen von Drupal:

      Installationsseite der Website auf der Drupal-Weboberfläche

      Nachdem die Website installiert ist, werden wir auf die Einrichtungsseite der Drupal-Website geleitet, um den Namen der Website, die E-Mail-Adresse, den Benutzernamen, das Passwort und die Ländereinstellungen zu konfigurieren. Geben Sie die Informationen an und klicken Sie auf Speichern und fortfahren:

      Konfigurationsseite der Website auf der Drupal-Weboberfläche

      Nachdem wir auf Speichern und fortfahren geklickt haben, sehen wir die Seite Willkommen bei Drupal. Diese zeigt uns, dass unsere Drupal-Website eingerichtet ist und erfolgreich ausgeführt wird.

      Seite Willkommen bei Drupal auf der Drupal-Weboberfläche

      Nachdem die Installation von Drupal nun abgeschlossen ist, müssen wir sicherstellen, dass unsere SSL-Zertifikate automatisch erneuert werden.

      Schritt 7 — Erneuern der Zertifikate

      Let’s-Encrypt-Zertifikate sind 90 Tage gültig. Daher müssen wir einen automatisierten Erneuerungsprozess einrichten, um sicherzustellen, dass sie nicht ablaufen. Eine Möglichkeit hierzu ist das Erstellen eines Jobs mit dem Planungsprogramm cron. In diesem Fall erstellen wir einen cron-Job, der in regelmäßigen Abständen ein Skript ausführt, das unsere Zertifikate erneuert und die Nginx-Konfiguration neu lädt.

      Wir erstellen die Datei ssl_renew.sh, um unsere Zertifikate zu erneuern:

      Fügen Sie folgenden Code hinzu. Denken Sie daran, den Verzeichnisnamen durch Ihren eigenen non-root user zu ersetzen:

      ~/drupal/ssl_renew.sh

      
      #!/bin/bash
      
      cd /home/sammy/drupal/
      /usr/local/bin/docker-compose -f docker-compose.yml run certbot renew --dry-run && 
      /usr/local/bin/docker-compose -f docker-compose.yml kill -s SIGHUP webserver
      

      Das Skript wechselt zum ~/drupal-Projektverzeichnis und führt die folgenden docker-compose-Befehle aus.

      • docker-compose run: Hiermit wird ein certbot-Container gestartet und der in unserer certbot-Dienstdefinition verfügbare command überschrieben. Anstatt des Unterbefehls certonly verwenden wir hier den Unterbefehl renew, mit dem Zertifikate, die kurz vor Ablauf stehen, erneuert werden. Wir haben hier die Option --dry-run zum Testen unseres Skripts hinzugefügt.

      • docker-compose kill: Hiermit wird ein SIGHUP-Signal an den webserver-Container gesendet, um die Nginx-Konfiguration neu zu laden.

      Schließen Sie die Datei und machen Sie sie mit folgendem Befehl ausführbar:

      • sudo chmod +x ssl_renew.sh

      Öffnen Sie als Nächstes die Datei root crontab, um das Erneuerungsskript in einem angegebenen Intervall auszuführen:

      Wenn Sie die Datei zum ersten Mal bearbeiten, werden Sie dazu aufgefordert, einen Texteditor zum Öffnen der Datei zu wählen:

      Output

      no crontab for root - using an empty one Select an editor. To change later, run 'select-editor'. 1. /bin/nano 2. /usr/bin/vim.basic 3. /usr/bin/vim.tiny 4. /bin/ed Choose 1-4 [1]: ...

      Fügen Sie am Ende der Datei die folgende Zeile hinzu und ersetzen Sie sammy mit Ihrem Benutzernamen:

      crontab

      ...
      */5 * * * * /home/sammy/drupal/ssl_renew.sh >> /var/log/cron.log 2>&1
      

      Hiermit wird das Job-Intervall auf alle fünf Minuten festgelegt, sodass wir testen können, ob unsere Erneuerungsanfrage wie beabsichtigt funktioniert hat oder nicht. Außerdem haben wir eine Protokolldatei, cron.log, zum Aufzeichnen der relevanten Ausgabe erstellt.

      Verwenden Sie nach fünf Minuten den Befehl tail, um cron.log zu prüfen und zu sehen, ob die Erneuerungsanfrage erfolgreich war oder nicht:

      • tail -f /var/log/cron.log

      Sie sehen eine Ausgabe, die eine erfolgreiche Erneuerung bestätigt:

      Output

      ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates below have not been saved.) Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/your_domain/fullchain.pem (success) ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates above have not been saved.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Drücken Sie STRG+C, um den tail-Prozess zu beenden.

      Wir können jetzt die Datei crontab ändern, um das Skript jeden zweiten Tag der Woche um 02:00 Uhr auszuführen. Ändern Sie die letzte Zeile der crontab wie folgt:

      crontab

      ...
      * 2 * * 2 /home/sammy/drupal/ssl_renew.sh >> /var/log/cron.log 2>&1
      

      Speichern und schließen Sie die Datei.

      Nun entfernen wir die Option --dry-run aus dem Skript ssl_renew.sh. Öffnen Sie es zunächst:

      Ändern Sie dann den Inhalt wie folgt:

      ~/drupal/ssl_renew.sh

      #!/bin/bash
      
      cd /home/sammy/drupal/
      /usr/local/bin/docker-compose -f docker-compose.yml run certbot renew && 
      /usr/local/bin/docker-compose -f docker-compose.yml kill -s SIGHUP webserver
      

      Unser cron-Job kümmert sich nun um den Ablauf unserer SSL-Zertifikate, indem er sie erneuert, wenn sie hierfür infrage kommen.

      Zusammenfassung

      In diesem Tutorial haben wir Docker Compose verwendet, um eine Drupal-Installation mit einem Nginx-Webserver zu erstellen. Als Teil des Workflows haben wir TLS/SSL-Zertifikate für die Domäne erlangt, mit der wir unsere Drupal-Website verknüpfen wollten, und einen cron-Job erstellt, um diese Zertifikate bei Bedarf zu erneuern.

      Wenn Sie mehr über Docker erfahren möchten, besuchen Sie unsere Docker-Themenseite.



      Source link

      Cómo instalar Drupal con Docker Compose


      El autor seleccionó a la Fundación de las Naciones Unidas para recibir una donación como parte del programa Write for DOnations.

      Kathleen Juell escribió la versión original de WordPress de este tutorial.

      Introducción

      Drupal es un sistema de administración de contenidos (CMS) escrito en PHP y se distribuye bajo la Licencia Pública General de GNU de código abierto. Personas y organizaciones en todo el mundo utilizan Drupal para impulsar sitios gubernamentales, blogs personales, empresas y más. Lo que distingue a Drupal de otras estructuras CMS es su creciente comunidad y un conjunto de funciones que incluyen procesos seguros, rendimiento fiable, modularidad y flexibilidad para adaptarse.

      Drupal requiere la instalación de las pilas LAMP (Linux, Apache, MySQL y PHP) o LEMP (Linux, Nginx, MySQL y PHP), pero la instalación de componentes individuales es una tarea larga. Podemos utilizar herramientas como Docker y Docker Compose para simplificar el proceso de instalación de Drupal. En este tutorial, se utilizarán imágenes de Docker para instalar componentes individuales en los contenedores de Docker. Al utilizar Docker Compose, podemos definir y administrar varios contenedores para la base de datos, la aplicación y la conexión/comunicación entre ellos.

      En este tutorial, instalaremos Drupal utilizando Docker Compose para poder aprovechar el uso de contenedores e implementar nuestro sitio web de Drupal en los servidores. Ejecutaremos contenedores para una base de datos de MySQL, un servidor web Nginx y Drupal. También protegeremos nuestra instalación obteniendo certificados TLS/SSL con Let’s Encrypt para el dominio que queremos asociar a nuestro sitio. Por último, configuraremos una tarea cron para renovar los certificados de modo que nuestro dominio permanezca seguro.

      Requisitos previos

      Para este tutorial, necesitaremos lo siguiente:

      • Un servidor con Ubuntu 18.04, un non-root user con privilegios sudo y un firewall activo. Para obtener información sobre cómo configurarlos, consulte esta guía de configuración inicial para servidores.
      • Docker instalado en su servidor conforme a los pasos 1 y 2 de Cómo instalar y usar Docker en Ubuntu 18.04. Este tutorial se probó en la versión 19.03.8.
      • Docker Compose instalado en su servidor conforme el paso 1 de Cómo instalar Docker Compose en Ubuntu 18.04. Este tutorial se probó en la versión 1.21.2.
      • Un nombre de dominio registrado. Para este tutorial, se utilizará your_domain en todo momento. Puede obtener un ejemplar gratis en Freenom o utilizar el registrador de dominios que desee.
      • Los dos registros DNS que se indican a continuación se configuraron para su servidor. Puede seguir esta introducción al DNS de DigitalOcean para obtener información sobre cómo agregarlos a una cuenta de DigitalOcean, si usa una:
        • Un registro A con your_domain orientado a la dirección IP pública de su servidor.
        • Un registro A con www.your_domain orientado a la dirección IP pública de su servidor.

      Paso 1: Definir la configuración del servidor web

      Antes de ejecutar cualquier contenedor, debemos definir la configuración de nuestro servidor web de Nginx. En nuestro archivo de configuración, se incluirán algunos bloques de ubicación específicos de Drupal y un bloque de ubicación para dirigir las solicitudes de verificación de Let´s Encrypt al cliente Certbot, a fin de renovar los certificados de manera automática.

      Primero, crearemos un directorio del proyecto para nuestra configuración de Drupal que denominaremos drupal:

      Diríjase al directorio que acaba de crear:

      Ahora podemos crear un directorio para nuestro archivo de configuración:

      Abra el archivo con nano o su editor de texto favorito:

      • nano nginx-conf/nginx.conf

      En este archivo, añadiremos un bloque de servidor con directivas para el nombre del servidor y el root del documento, bloques de ubicación para dirigir la solicitud de certificados del cliente de Certbot, procesamiento de PHP y solicitudes de recursos estáticos.

      Agregue el siguiente código al archivo. Asegúrese de sustituir your_domain por su propio nombre de dominio:

      ~/drupal/nginx-conf/nginx.conf

      server {
          listen 80;
          listen [::]:80;
      
          server_name your_domain www.your_domain;
      
          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;
          }
      
          rewrite ^/core/authorize.php/core/authorize.php(.*)$ /core/authorize.php$1;
      
          location ~ .php$ {
              try_files $uri =404;
              fastcgi_split_path_info ^(.+.php)(/.+)$;
              fastcgi_pass drupal: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;
          }
      }
      

      Nuestro bloque de servidor incluye la siguiente información:

      Directivas:

      • listen: indica a Nginx que escuche en el puerto 80, lo que nos permitirá utilizar el complemento webroot de Certbot para nuestras solicitudes de certificados. Tenga en cuenta que aún no incluiremos el puerto 443; actualizaremos nuestra configuración para incluir SSL una vez que hayamos obtenido nuestros certificados de manera exitosa.

      • server_name: define el nombre de nuestro servidor y el bloque de servidor que debería utilizarse para las solicitudes a nuestro servidor. Asegúrese de sustituir your_domain en esta línea por su propio nombre de dominio.

      • index: la directiva index define los archivos que se utilizarán como índices al procesar las solicitudes a nuestro servidor. En este caso, modificamos el orden de prioridad predeterminado moviendo index.php antes de index.html para que Nginx priorice los archivos llamados index.php cuando sea posible.

      • root: nuestra directiva root nombra el directorio root para las solicitudes a nuestro servidor. Este directorio, /var/www/html, se crea como punto de montaje en el momento de la compilación siguiendo las instrucciones de nuestro Drupal Dockerfile. Estas instrucciones de Dockerfile también garantizan que los archivos de la versión de Drupal se monten en este volumen.

      • rewrite: si la expresión regular especificada (^/core/authorize.php/core/authorize.php(.*)$) coincide con una solicitud URI, el URI se modifica según lo especificado en la cadena de sustitución (/core/authorized.php$1).

      Bloques de ubicación:

      • location ~ /.well-known/acme-challenge: este bloque de ubicación manejará las solicitudes al directorio .well-known, donde Certbot creará un archivo temporal para validar la resolución del DNS de nuestro dominio en nuestro servidor. Una vez implementada esta configuración, podremos utilizar el complemento webroot de Certbot para obtener los certificados para nuestro dominio.

      • location /: en este bloque de ubicación, utilizaremos una directiva try_files para buscar archivos que coincidan con solicitudes del URI individuales. Sin embargo, en lugar de devolver un estado 404 Not Found por defecto, pasaremos el control al archivo index.php de Drupal con los argumentos de solicitud.

      • location ~ .php$: este bloque de ubicación se encargará del procesamiento de PHP y servirá como proxy de estas solicitudes a nuestro contenedor drupal. Debido a que nuestra imagen de Docker de Drupal se basará en la imagen php:fpm, también incluiremos opciones de configuración que son específicas para el protocolo FastCGI en este bloque. Nginx requiere un procesador de PHP independiente para solicitudes de PHP: en nuestro caso, estas solicitudes estarán a cargo del procesador php-fpm que está incluido con la imagen php:fpm. Además, este bloque de ubicación incluye directivas, variables y opciones específicas de FastCGI que actuarán como proxy para las solicitudes a la aplicación de Drupal que se ejecuten en nuestro contenedor Drupal, establecerán el índice preferido para el identificador URI de la solicitud analizada, y analizarán las solicitudes de URI.

      • location ~ /.ht: este bloque se encargará de los archivos .htaccess, ya que Nginx no los proporcionará. La directiva deny_all garantiza que los archivos de .htaccess nunca se proporcionarán a los usuarios.

      • location = /favicon.ico, location = /robots.txt: estos bloques garantizan que las solicitudes a /favicon.ico y /robots.txt no se registren.

      • location ~* .(css|gif|ico|jpeg|jpg|js|png)$: este bloque desactiva el registro para solicitudes de activos estáticos y garantiza que estos activos tengan altas condiciones de almacenamiento en caché, ya que normalmente su mantenimiento es costoso.

      Para obtener más información sobre proxy de FastCGI, consulte el artículo Información e implementación de proxy de FastCGI en Nginx. Para obtener información sobre los bloques de servidor y ubicación, consulte el artículo Información sobre algoritmos de selección de bloques de servidores y ubicación de Nginx.

      Guarde y cierre el archivo cuando concluya la edición.

      Una vez implementada su configuración de Nginx, puede crear variables de entorno para pasarlas a su aplicación y contenedores de bases de datos en tiempo de ejecución.

      Paso 2: Definir variables de entorno

      Nuestra aplicación de Drupal necesita una base de datos (MySQL, PostgresSQL, etc.) para guardar la información relacionada con el sitio. El contenedor de Drupal necesitará acceso a ciertas variables de entorno al momento de ejecución para acceder al contenedor de la base de datos (MySQL). Estas variables contienen la información confidencial, como las credenciales de la base de datos, por lo que no podemos exponerlas directamente en el archivo de Docker Compose, el archivo principal que contiene información sobre cómo se ejecutarán nuestros contenedores.

      Siempre se recomienda establecer los valores confidenciales en el archivo .env y restringir su circulación. Esto impedirá que estos valores se copien en los repositorios de nuestro proyecto y se expongan al público.

      En el directorio principal del proyecto, ~/drupal, cree y abra un archivo denominado .env:

      Agregue las siguientes variables al archivo .env y sustituya las secciones resaltadas con las credenciales que quiere utilizar:

      ~/drupal/.env

      MYSQL_ROOT_PASSWORD=root_password
      MYSQL_DATABASE=drupal
      MYSQL_USER=drupal_database_user
      MYSQL_PASSWORD=drupal_database_password
      

      Hemos agregado una contraseña para la cuenta administrativa root de MySQL, además de nuestro nombre de usuario y contraseña preferidos para la base de datos de nuestra aplicación.

      Nuestro archivo .env contiene información confidencial, por lo que siempre se recomienda incluirlo en los archivos .gitignore y .dockerignore de un proyecto para que no se añada en nuestros repositorios de Git e imágenes de Docker.

      Si planea trabajar con Git para el control de versiones, inicialice su directorio de trabajo actual como un repositorio con git init:

      Abra el archivo .gitignore:

      Agregue lo siguiente:

      ~/drupal/.gitignore

      .env
      

      Guarde el archivo y ciérrelo.

      De manera similar, abra el archivo .dockerignore:

      Luego, agregue lo siguiente:

      ~/drupal/.dockerignore

      .env
      .git
      

      Guarde el archivo y ciérrelo.

      Ahora que hemos tomado medidas para proteger nuestras credenciales como variables de entorno, vayamos al siguiente paso para definir nuestros servicios en un archivo docker-compose.yml.

      Paso 3: Definir servicios con Docker Compose

      Docker Compose es una herramienta para definir y ejecutar aplicaciones de Docker de varios contenedores. Definimos un archivo YAML para configurar los servicios de nuestra aplicación. Un servicio en Docker Compose es un contenedor en ejecución, y Compose nos permite vincular estos servicios con volúmenes y redes compartidos.

      Crearemos contenedores diferentes para la aplicación, la base de datos y el servidor web de Drupal. Además, también crearemos un contenedor para ejecutar Certbot, a fin de obtener los certificados para nuestro servidor web.

      Cree un archivo docker-compose.yml:

      Agregue el siguiente código para definir la versión del archivo de Compose y el servicio de base de datos mysql:

      ~/drupal/docker-compose.yml

      version: "3"
      
      services:
        mysql:
          image: mysql:8.0
          container_name: mysql
          command: --default-authentication-plugin=mysql_native_password
          restart: unless-stopped
          env_file: .env
          volumes:
            - db-data:/var/lib/mysql
          networks:
            - internal
      

      Analicemos cada uno con todas las opciones de configuración del servicio mysql:

      • image: especifica la imagen que se utilizará/extraerá para crear el contenedor. Siempre se recomienda utilizar la imagen con la etiqueta de la versión adecuada, y excluir la etiqueta latest para evitar conflictos futuros. Puedes obtener más información sobre las Prácticas recomendadas de Dockerfile en la documentación de Docker.

      • container_name: sirve para definir el nombre del contenedor.

      • command: se utiliza para anular el comando predeterminado (instrucción CMD) en la imagen. MySQL admite diferentes complementos de autenticación, pero mysql_native_password es el método tradicional para autenticar. Ya que PHP, y por lo tanto, Drupal, no admite la autenticación más reciente de MySQL, debemos establecer --default-authentication-plugin=mysql_native_password como el mecanismo de autenticación predeterminado.

      • restart: se utiliza para definir la política de reinicio del contenedor. La política unless-stopped reinicia un contenedor a menos que se detenga manualmente.

      • env_file: añade las variables de entorno desde un archivo. En nuestro caso, leerá las variables de entorno del archivo .env que definimos en el paso anterior.

      • volumes: monta rutas host o volúmenes con nombre, que se especificaron como subopciones de un servicio. Vamos a montar un volumen con nombre denominado db-data al directorio /var/lib/mysql en el contenedor, donde por defecto MySQL escribirá sus archivos de datos.

      • networks: define la red interna a la que se unirá nuestro servicio de aplicación. Definiremos las redes al final del archivo.

      Ya hemos definido la definición de nuestro servicio mysql, así que ahora agregaremos la definición del servicio de la aplicación de drupal al final del archivo:

      ~/drupal/docker-compose.yml

      ...
        drupal:
          image: drupal:8.7.8-fpm-alpine
          container_name: drupal
          depends_on:
            - mysql
          restart: unless-stopped
          networks:
            - internal
            - external
          volumes:
            - drupal-data:/var/www/html
      

      En esta definición del servicio, nombraremos nuestro contenedor y definiremos una política de reinicio, tal como lo hicimos con el servicio mysql. También añadiremos algunas opciones específicas para este contenedor:

      • image: aquí utilizamos la imagen de Drupal 8.7.8-fpm-alpine. Esta imagen tiene el procesador php-fpm que requiere nuestro servidor web de Nginx para administrar el procesamiento de PHP. Además, utilizamos la imagen alpine, proveniente del proyecto Alpine Linux, que reducirá el tamaño de la imagen en general y cuyo uso se aconseja en las prácticas recomendadas de Dockerfile. Drupal tiene más versiones de imágenes que puedes descubrir en Dockerhub.

      • depends_on: se utiliza para expresar dependencia entre los servicios. Definir el servicio mysql como la dependencia a nuestro contenedor drupal garantizará que nuestro contenedor drupal se cree después del contenedor mysql y habilitará nuestra aplicación para que se inicie sin problemas.

      • networks: aquí hemos agregado este contenedor a la red externa junto con la red interna. Esto garantizará que nuestro servicio mysql sea accesible únicamente desde el contenedor drupal a través de la red interna, y al mismo tiempo mantendrá este contenedor accesible para otros contenedores por medio de la red externa.

      • volumes: montaremos un volumen con nombre denominado drupal-data al punto de montaje /var/www/html creado por la imagen de Drupal. Usar un volumen con nombre de esta manera nos permitirá compartir el código de nuestra aplicación con otros contenedores.

      A continuación, añadiremos la definición del servicio de Nginx después de la definición del servicio de drupal:

      ~/drupal/docker-compose.yml

      ...
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      

      De nuevo, nombraremos nuestro contenedor y haremos que dependa del contenedor de Drupal por orden de inicio. También utilizaremos una imagen alpine: la imagen de Nginx 1.17.4-alpine.

      Esta definición de servicio también incluye las siguientes opciones:

      • ports: expone el puerto 80 para habilitar las opciones de configuración que definimos en nuestro archivo nginx.conf en el paso 1.

      • volumes: aquí definimos tanto el volumen con nombre como la ruta host:

        • drupal-data:/var/www/html: montará el código de nuestra aplicación de Drupal al directorio /var/www/html, el que configuramos como root en nuestro bloque de servidor de Nginx.
        • ./nginx-conf:/etc/nginx/conf.d: montará el directorio de configuración de Nginx en el host al directorio pertinente del contenedor, lo cual garantizará que cualquier cambio que realicemos en los archivos del host se refleje en el contenedor.
        • certbot-etc:/etc/letsencrypt: montará los certificados y las claves pertinentes de Let’s Encrypt para nuestro dominio al directorio correspondiente del contenedor.
        • networks: hemos definido la red externa para que este contenedor solo se comunique con el contenedor drupal y no con el contenedor mysql.

      Por último, agregaremos la última definición del servicio para el servicio certbot. Asegúrese de sustituir sammy@your_domain y your_domain por su correo electrónico y nombre de dominio:

      ~/drupal/docker-compose.yml

      ...
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
      

      Esta definición indica a Compose que introduzca la imagen certbot/certbot de Docker Hub. También utiliza volúmen con nombre para compartir recursos con el contenedor de Nginx, incluidos los certificados de dominio y la clave en certbot-etc, y el código de la aplicación en drupal-data.

      También hemos utilizado depends_on para asegurarnos de que el contenedor certbot se inicie tras la ejecución del servicio del servidor web.

      Aquí no hemos especificado ninguna red, porque este contenedor no se comunicará a ningún servicio a través de la red. Solo añade los certificados de dominio y la clave, que hemos montado utilizando los volúmenes con nombre.

      También incluimos una opción de command que especifica un subcomando que debe ejecutarse con el comando de certbot predeterminado del contenedor. El cliente de Certbot admite complementos para obtener e instalar certificados. Incluimos certonly y --webroot en la línea de comandos para utilizar el complemento webroot para obtener un certificado. Puede encontrar más información sobre el complemento y los comandos adicionales en la documentación oficial de Certbot.

      Debajo de la definición de servicio certbot, agregue las definiciones de red y volumen:

      ~/drupal/docker-compose.yml

      ...
      networks:
        external:
          driver: bridge
        internal:
          driver: bridge
      
      volumes:
        drupal-data:
        db-data:
        certbot-etc:
      

      La clave networks de nivel superior nos permite especificar las redes que debemos crear. networks permite la comunicación entre los servicios/contenedores en todos los puertos, ya que están en el mismo host de demonio de Docker. Hemos definido dos redes: internal y external, para proteger la comunicación de los servicios del servidor web, drupal y mysql.

      La clave volumes se utiliza para definir los volúmenes con nombre drupal-data, db-data y certbot-etc. Cuando Docker crea volúmenes, el contenido del volumen se almacena en un directorio del sistema de archivos host, /var/lib/docker/volumes/, que Docker administra. El contenido de cada volumen luego se monta desde este directorio en cualquier contenedor que utilice el volumen en cuestión. De esta manera, es posible compartir códigos y datos entre contenedores.

      El archivo docker-compose.yml terminado tendrá este aspecto:

      ~/drupal/docker-compose.yml

      version: "3"
      
      services:
        mysql:
          image: mysql:8.0
          container_name: mysql
          command: --default-authentication-plugin=mysql_native_password
          restart: unless-stopped
          env_file: .env
          volumes:
            - db-data:/var/lib/mysql
          networks:
            - internal
      
        drupal:
          image: drupal:8.7.8-fpm-alpine
          container_name: drupal
          depends_on:
            - mysql
          restart: unless-stopped
          networks:
            - internal
            - external
          volumes:
            - drupal-data:/var/www/html
      
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
      
      networks:
        external:
          driver: bridge
        internal:
          driver: bridge
      
      volumes:
        drupal-data:
        db-data:
        certbot-etc:
      

      Ya terminamos de definir nuestros servicios. A continuación, iniciaremos el contenedor y probaremos nuestras solicitudes de certificado.

      Paso 4: Obtener certificados y credenciales SSL

      Podemos iniciar nuestros contenedores con el comando docker-compose up, que creará y ejecutará nuestros contenedores en el orden que especificamos. Si las solicitudes de nuestros dominios tienen éxito, veremos el estado de salida correcto en nuestro resultado y los certificados correctos montados en la carpeta /etc/letsencrypt/live del contenedor del servidor web.

      Para ejecutar los contenedores en segundo plano, utilice el comando docker-compose up con el indicador -d:

      Verá un resultado similar que confirmará la creación de sus servicios:

      Output

      ... Creating mysql ... done Creating drupal ... done Creating webserver ... done Creating certbot ... done

      Compruebe el estado de los servicios utilizando el comando docker-compose ps:

      Veremos los servicios mysql, drupal y webserver con un State (estado) de valor Up, a la vez que certbot arrojará un mensaje de estado con valor 0:

      Output

      Name Command State Ports -------------------------------------------------------------------------- certbot certbot certonly --webroot ... Exit 0 drupal docker-php-entrypoint php-fpm Up 9000/tcp mysql docker-entrypoint.sh --def ... Up 3306/tcp, 33060/tcp webserver nginx -g daemon off; Up 0.0.0.0:80->80/tcp

      Si ve algo diferente de Up en la columna State para los servicios mysql, drupal o webserver, o un estado de salida distinto a 0 para el contenedor certbot, asegúrese de verificar los registros de servicio con el comando docker-compose logs:

      • docker-compose logs service_name

      Ahora podemos verificar que nuestros certificados estén montados en el contenedor webserver utilizando el comando docker-compose exec:

      • docker-compose exec webserver ls -la /etc/letsencrypt/live

      Esto generará el siguiente resultado:

      Output

      total 16 drwx------ 3 root root 4096 Oct 5 09:15 . drwxr-xr-x 9 root root 4096 Oct 5 09:15 .. -rw-r--r-- 1 root root 740 Oct 5 09:15 README drwxr-xr-x 2 root root 4096 Oct 5 09:15 your_domain

      Ahora que todo se ejecuta correctamente, podemos editar la definición de nuestro servicio de certbot para eliminar el indicador --staging.

      Abra el archivo docker-compose.yml, vaya a la definición de servicio de certbot y sustituya el indicador --staging en la opción de comando por el indicador --force-renewal, el cual indicará a Certbot que quiere solicitar un nuevo certificado con los mismos dominios que un certificado existente. La definición actualizada de certbot tendrá este aspecto:

      ~/drupal/docker-compose.yml

      ...
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
      ...
      

      Tenemos que ejecutar docker-compose up de nuevo para recrear el contenedor de certbot. También incluiremos la opción --no-deps para indicar a Compose que puede omitir el inicio del servicio webserver, dado que ya está en ejecución:

      • docker-compose up --force-recreate --no-deps certbot

      Veremos un resultado que indicará que nuestra solicitud de certificado fue exitosa:

      Output

      Recreating certbot ... done Attaching to certbot certbot | Saving debug log to /var/log/letsencrypt/letsencrypt.log certbot | Plugins selected: Authenticator webroot, Installer None certbot | Renewing an existing certificate certbot | Performing the following challenges: certbot | http-01 challenge for your_domain certbot | http-01 challenge for www.your_domain certbot | Using the webroot path /var/www/html for all unmatched domains. certbot | Waiting for verification... certbot | Cleaning up challenges certbot | IMPORTANT NOTES: certbot | - Congratulations! Your certificate and chain have been saved at: certbot | /etc/letsencrypt/live/your_domain/fullchain.pem certbot | Your key file has been saved at: certbot | /etc/letsencrypt/live/your_domain/privkey.pem certbot | Your cert will expire on 2020-01-03. To obtain a new or tweaked certbot | version of this certificate in the future, simply run certbot certbot | again. To non-interactively renew *all* of your certificates, run certbot | "certbot renew" certbot | - Your account credentials have been saved in your Certbot certbot | configuration directory at /etc/letsencrypt. You should make a certbot | secure backup of this folder now. This configuration directory will certbot | also contain certificates and private keys obtained by Certbot so certbot | making regular backups of this folder is ideal. certbot | - If you like Certbot, please consider supporting our work by: certbot | certbot | Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate certbot | Donating to EFF: https://eff.org/donate-le certbot | certbot exited with code 0

      Una vez que hayamos generado correctamente nuestros certificados, podemos actualizar nuestra configuración de Nginx para incluir SSL.

      Paso 5: Modificar la configuración del servidor web y la definición del servicio

      Después de instalar los certificados SSL en Nginx, tendremos que redirigir todas las solicitudes de HTTP a HTTPS. También tendremos que especificar las ubicaciones de nuestro certificado SSL y de la clave, y agregar encabezados y parámetros de seguridad.

      Debido a que recreará el servicio webserver para incluir estas adiciones, puede detenerlo ahora:

      • docker-compose stop webserver

      Esto generará el siguiente resultado:

      Output

      Stopping webserver ... done

      A continuación, vamos a eliminar el archivo de configuración de Nginx que creamos anteriormente:

      Abra otra versión del archivo:

      • nano nginx-conf/nginx.conf

      Añada el siguiente código al archivo para redireccionar HTTP a HTTP y para agregar credenciales, protocolos y encabezados de seguridad SSL. Recuerde sustituir your_domain por su dominio:

      ~/drupal/nginx-conf/nginx.conf

      server {
          listen 80;
          listen [::]:80;
      
          server_name your_domain www.your_domain;
      
          location ~ /.well-known/acme-challenge {
              allow all;
              root /var/www/html;
          }
      
          location / {
              rewrite ^ https://$host$request_uri? permanent;
          }
      }
      server {
          listen 443 ssl;
          listen [::]:443 ssl;
          server_name your_domain www.your_domain;
      
          index index.php index.html index.htm;
      
          root /var/www/html;
      
          server_tokens off;
      
          ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
          ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
      
          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-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
      
          location / {
              try_files $uri $uri/ /index.php$is_args$args;
          }
      
          rewrite ^/core/authorize.php/core/authorize.php(.*)$ /core/authorize.php$1;
      
          location ~ .php$ {
              try_files $uri =404;
              fastcgi_split_path_info ^(.+.php)(/.+)$;
              fastcgi_pass drupal: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;
          }
      }
      

      El bloque de servidor HTTP especifica el complemento webroot para solicitudes de renovación de Certbot al directorio .well-known/acme-challenge. También incluye una directiva de reescritura que dirige las solicitudes HTTP al directorio root hacia HTTPS.

      El bloque de servidor HTTPS habilita ssl y http2. Para obtener más información sobre la iteración de HTTP/2 en protocolos HTTP y los beneficios que puede tener para el rendimiento de sitios web, consulte la introducción de Cómo configurar Nginx con compatibilidad para HTTP/2 en Ubuntu 18.04.

      Estos bloques habilitan SSL, ya que hemos incluido las ubicaciones de nuestro certificado SSL y de la clave junto con los encabezados recomendados. Estos encabezados nos permitirán obtener una clasificación A en los sitios de prueba de servidores de SSL Labs y Security Headers.

      Nuestras directivas root e index también se encuentran en este bloque, al igual que el resto de los bloques de ubicación específicos de Drupal que analizamos en el paso 1.

      Guarde y cierre el archivo de configuración actualizado de Nginx.

      Antes de comenzar a recrear el contenedor de webserver, tendremos que agregar una asignación de puerto 443 a la definición de nuestro servicio de webserver, ya que hemos habilitado los certificados SSL.

      Abra el archivo docker-compose.yml:

      Realice las siguientes modificaciones de la definición de servicio de webserver:

      ~/drupal/docker-compose.yml

      ...
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
            - 443:443
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      ...
      

      Después de habilitar los certificados SSL, nuestro docker-compose.yml se verá de la siguiente manera:

      ~/drupal/docker-compose.yml

      version: "3"
      
      services:
        mysql:
          image: mysql:8.0
          container_name: mysql
          command: --default-authentication-plugin=mysql_native_password
          restart: unless-stopped
          env_file: .env
          volumes:
            - db-data:/var/lib/mysql
          networks:
            - internal
      
        drupal:
          image: drupal:8.7.8-fpm-alpine
          container_name: drupal
          depends_on:
            - mysql
          restart: unless-stopped
          networks:
            - internal
            - external
          volumes:
            - drupal-data:/var/www/html
      
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
            - 443:443
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
      
      networks:
        external:
          driver: bridge
        internal:
          driver: bridge
      
      volumes:
        drupal-data:
        db-data:
        certbot-etc:
      

      Guarde y cierre el archivo. Ahora crearemos el servicio webserver con nuestra configuración actualizada:

      • docker-compose up -d --force-recreate --no-deps webserver

      Esto generará el siguiente resultado:

      Output

      Recreating webserver ... done

      Compruebe los servicios con docker-compose ps:

      Veremos los servicios de mysql, drupal y webserver como Up, mientras que certbot arrojará un mensaje de estado con valor 0:

      Output

      Name Command State Ports -------------------------------------------------------------------------- certbot certbot certonly --webroot ... Exit 0 drupal docker-php-entrypoint php-fpm Up 9000/tcp mysql docker-entrypoint.sh --def ... Up 3306/tcp, 33060/tcp webserver nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp

      Ahora, todos nuestros servicios se están ejecutando y podemos continuar con la instalación de Drupal a través de la interfaz web.

      Paso 6: Completar la instalación a través de la interfaz web

      Completaremos la instalación mediante la interfaz web de Drupal.

      En un navegador web, diríjase al dominio del servidor. Recuerde sustituir aquí your_domain por su propio nombre de dominio:

      https://your_domain
      

      Seleccione el idioma que utilizará:

      Página Seleccionar idioma en la interfaz web de Drupal

      Haga clic en Guardar y continuar. Llegaremos a la página de Perfil de instalación. Drupal tiene varios perfiles, así que seleccione el perfil Estándar y haga clic en Guardar y continuar.

      Página Seleccionar perfil en la interfaz web de Drupal

      Después de seleccionar el perfil, pasaremos a la página de Configuración de la base de datos. Seleccione el tipo de base de datos MySQL, MariaDB, Percona Server o equivalente y escriba los valores de nombre de la base de datos, usuario y contraseña que se corresponden con los valores de MYSQL_DATABASE, MYSQL_USER y MYSQL_PASSWORD, respectivamente, los cuales definimos en el archivo .env en el paso 2. Haga clic en Opciones avanzadas y utilice el nombre del contenedor de servicio mysql para el valor de Host. Haga clic en Guardar y continuar.

      Página Configurar la base de datos en la interfaz web de Drupal

      Después de configurar la base de datos, se comenzarán a instalar los módulos y los temas predeterminados de Drupal:

      Página Instalar sitio en la interfaz web de Drupal

      Cuando se haya instalado el sitio, llegaremos a la página de configuración del sitio de Drupal en donde podremos establecer el nombre del sitio, el correo electrónico, el usuario, la contraseña y la configuración regional. Complete la información y haga clic en Guardar y continuar:

      Página Configurar sitio en la interfaz web de Drupal

      Después de hacer clic en Guardar y continuar, podemos ver la página Bienvenido a Drupal que muestra que nuestro sitio de Drupal está listo y funciona correctamente.

      Página Bienvenido a Drupal en la interfaz web de Drupal

      Ahora que completamos la instalación de Drupal,debemos asegurarnos de que nuestros certificados SSL se renueven automáticamente.

      Paso 7: Renovar certificados

      Los certificados de Let’s Encrypt son válidos durante 90 días, por lo que tenemos que configurar un proceso de renovación automática para asegurarnos de que no caduquen. Una forma de hacerlo es crear una tarea con la utilidad de programación cron. En este caso, crearemos una tarea cron para que de forma periódica ejecute una secuencia de comandos que renovará nuestros certificados y volverá a cargar nuestra configuración de Nginx.

      Vamos a crear el archivo ssl_renew.sh para renovar los certificados:

      Agregue el siguiente código: Recuerde sustituir el nombre del directorio por su non-root user:

      ~/drupal/ssl_renew.sh

      
      #!/bin/bash
      
      cd /home/sammy/drupal/
      /usr/local/bin/docker-compose -f docker-compose.yml run certbot renew --dry-run && 
      /usr/local/bin/docker-compose -f docker-compose.yml kill -s SIGHUP webserver
      

      Esta secuencia de comandos cambia al directorio del proyecto ~/drupal y ejecuta los siguientes comandos docker-compose.

      • docker-compose run: iniciará un contenedor certbot y anulará el command proporcionado en nuestra definición de servicio certbot. En lugar de usar el subcomando de certonly, utilizaremos aquí el subcomando renew que renovará los certificados que caducarán pronto. En este caso, incluimos la opción --dry-run para probar nuestra secuencia de comandos.

      • docker-compose kill: enviará una señal de SIGHUP al contenedor webserver para volver a cargar la configuración de Nginx.

      Cierre el archivo y utilice el siguiente comando para que sea ejecutable:

      • sudo chmod +x ssl_renew.sh

      A continuación, abra el archivo root crontab para ejecutar la secuencia de comandos de renovación en un intervalo especificado:

      Si es la primera vez que edita este archivo, se le solicitará elegir un editor de texto para abrir el archivo:

      Output

      no crontab for root - using an empty one Select an editor. To change later, run 'select-editor'. 1. /bin/nano 2. /usr/bin/vim.basic 3. /usr/bin/vim.tiny 4. /bin/ed Choose 1-4 [1]: ...

      Al final del archivo, agregue la siguiente línea, en la que reemplazará sammy por su nombre de usuario:

      crontab

      ...
      */5 * * * * /home/sammy/drupal/ssl_renew.sh >> /var/log/cron.log 2>&1
      

      Esto fijará un intervalo de tarea de cinco minutos, para que podamos probar si la solicitud de renovación funciona como estaba previsto. También creamos un archivo de registro, cron.log para registrar el resultado pertinente de la tarea.

      Pasados cinco minutos, utilice el comando tail para verificar cron.log y ver si la solicitud de renovación fue exitosa:

      • tail -f /var/log/cron.log

      Verá un resultado que confirme el éxito de la renovación:

      Output

      ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates below have not been saved.) Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/your_domain/fullchain.pem (success) ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates above have not been saved.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Presione CTRL+C para abandonar el proceso tail.

      Ahora podemos modificar el archivo crontab para ejecutar la secuencia de comandos el segundo día de todas las semanas a las 2:00. Modifique la última línea de crontab como se muestra:

      crontab

      ...
      * 2 * * 2 /home/sammy/drupal/ssl_renew.sh >> /var/log/cron.log 2>&1
      

      Guarde y cierre el archivo.

      Ahora, eliminaremos la opción --dry-run de la secuencia de comandos ssl_renew.sh. Primero, ábralo:

      Luego, modifique el contenido como se muestra a continuación:

      ~/drupal/ssl_renew.sh

      #!/bin/bash
      
      cd /home/sammy/drupal/
      /usr/local/bin/docker-compose -f docker-compose.yml run certbot renew && 
      /usr/local/bin/docker-compose -f docker-compose.yml kill -s SIGHUP webserver
      

      Ahora, nuestra tarea cron evitará el vencimiento de los certificados SSL al renovarlos cuando sean elegibles.

      Conclusión

      En este tutorial, utilizamos Docker Compose para crear una instalación de Drupal con un servidor web de Nginx. Como parte de este flujo de trabajo, obtuvimos los certificados TLS/SSL para el dominio que queríamos asociar a nuestro sitio de Drupal y creamos una tarea cron para renovar los certificados cuando sea necesario.

      Si quiere obtener más información sobre Docker, consulte nuestra página temática dedicada a Docker.



      Source link

      Установка Drupal с помощью Docker Compose


      Автор выбрал фонд Организации Объединенных Наций для получения пожертвования в рамках программы Write for DOnations.

      Оригинальная версия WordPress этого обучающего руководства была написана Кэйтлин Джуэлл (Kathleen Juell).

      Введение

      Drupal — это система управления контентом (CMS), написанная на PHP и распространяемая по универсальной общественной лицензии GNU с открытым исходным кодом. Люди и организации по всему миру используют Drupal для управления правительственными сайтами, ведения личных блогов, бизнеса и не только. Уникальные отличия Drupal от других структур CMS: растущее сообщество и набор функций, которые включают безопасные процессы, надежную работу и адаптивность.

      Для Drupal необходимо установить стек LAMP (Linux, Apache, MySQL и PHP) или LEMP (Linux, Nginx, MySQL и PHP), но установка компонентов по отдельности занимает много времени. Для упрощения процесса установки Drupal мы можем использовать такие инструменты, как Docker и Docker Compose. В этом обучающем руководстве будут использованы образы Docker для установки отдельных компонентов в Docker-контейнерах. С помощью Docker Compose мы можем определять и управлять несколькими контейнерами для базы данных, приложения, а также взаимодействием/коммуникацией между ними.

      В этом обучающем руководстве мы установим Drupal с помощью Docker Compose для возможности контейнеризации и развертывания нашего веб-сайта Drupal на серверах. Мы запустим контейнеры для базы данных MySQL, веб-сервера Nginx и системы Drupal. Также мы защитим нашу установку, получив сертификаты TLS/SSL с Let’s Encrypt​​​ для домена, который мы хотим ассоциировать с нашим сайтом. Наконец, мы настроим задание cron для обновления ваших сертификатов, чтобы домен оставался защищенным.

      Предварительные требования

      Для данного обучающего руководства нам потребуется следующее:

      • Сервер на базе Ubuntu 18.04, а также non-root user с привилегиями sudo и активный брандмауэр. Дополнительную информацию о настройке этих параметров см. в руководстве по первоначальной настройке сервера.
      • Система Docker, установленная на сервере в соответствии с шагами 1 и 2 руководства Установка и использование Docker в Ubuntu 18.04. Это обучающее руководство было протестировано на версии 19.03.8.
      • Docker Compose, установленный на сервере в соответствии с шагом 1 руководства Установка Docker Compose в Ubuntu 18.04. Это обучающее руководство было протестировано на версии 1.21.2.
      • Зарегистрированное доменное имя. В этом обучающем руководстве мы будем использовать your_domain. Вы можете получить бесплатный домен на Freenom или зарегистрировать доменное имя по вашему выбору.
      • На вашем сервере должны быть настроены обе нижеследующие записи DNS. Вы можете воспользоваться введением в работу с DigitalOcean DNS, чтобы получить подробную информацию о добавлении доменов в учетную запись DigitalOcean, если вы используете этот способ:
        • Запись A, где your_domain указывает на публичный IP-адрес вашего сервера.
        • Запись A, где www.your_domain указывает на публичный IP-адрес вашего сервера.

      Шаг 1 — Настройка конфигурации веб-сервера

      Перед запуском контейнеров нам нужно определить конфигурацию для нашего веб-сервера Nginx. Наш файл конфигурации будет включать несколько специфических для Drupal блоков расположения наряду с блоками расположения, которые будут направлять передаваемые запросы верификации Let’s Encrypt клиенту Certbot для автоматизированного обновления сертификатов.

      Вначале создадим директорию проекта для нашей настройки Drupal с именем drupal:

      Перейдите в недавно созданную директорию:

      Теперь мы можем создать директорию для нашего файла конфигурации:

      Откройте файл с помощью nano или своего любимого редактора:

      • nano nginx-conf/nginx.conf

      В этом файле мы добавим серверный блок с директивами для имени нашего сервера и корневой директории документов, а также блок расположения для направления запросов сертификатов от клиента Certbot, обработки PHP и запросов статичных активов.

      Добавьте в этот файл следующий код. Обязательно замените your_domain на ваше доменное имя:

      ~/drupal/nginx-conf/nginx.conf

      server {
          listen 80;
          listen [::]:80;
      
          server_name your_domain www.your_domain;
      
          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;
          }
      
          rewrite ^/core/authorize.php/core/authorize.php(.*)$ /core/authorize.php$1;
      
          location ~ .php$ {
              try_files $uri =404;
              fastcgi_split_path_info ^(.+.php)(/.+)$;
              fastcgi_pass drupal: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;
          }
      }
      

      Наш серверный блок содержит следующую информацию:

      Директивы:

      • listen: данный элемент просит Nginx прослушивать порт 80, что позволит нам использовать плагин webroot Certbot для наших запросов сертификатов. Обратите внимание, что мы пока не будем включать порт 443, мы обновим нашу конфигурацию и добавим SSL после успешного получения наших сертификатов.

      • server_name: этот элемент определяет имя нашего сервера и серверный блок, которые должны использоваться для запросов к нашему серверу. Обязательно замените your_domain в этой строке на ваше собственное доменное имя.

      • index: директива index определяет файлы, которые будут использоваться в качестве индексов при обработке запросов к нашему серверу. Здесь мы изменили порядок приоритета по умолчанию, поставив index.php перед index.html, в результате чего Nginx будет давать приоритет файлам с именем index.php при наличии возможности.

      • root: наша директива root назначает имя корневой директории для запросов к нашему серверу. Эта директория, /var/www/html, создается в качестве точки монтирования в момент сборки с помощью инструкций в файле Dockerfile Drupal. Эти инструкции Dockerfile также гарантируют, что файлы релиза Drupal монтируются в этот том.

      • rewrite: если указанное регулярное выражение (^/core/authorize.php/core/authorize.php(.*)$) соответствует запросу URI, URI меняется согласно указаниям в строке замены (/core/authorize.php$1).

      Блоки расположения:

      • location ~ /.well-known/acme-challenge: этот блок расположения будет обрабатывать запросы в директории .well-known, где Certbot будет размещать временный файл для подтверждения того, что DNS для нашего домена будет работать с нашим сервером. Настроив данную конфигурацию, мы сможем использовать плагин webroot Certbot для получения сертификатов для нашего домена.

      • location /: в этом блоке расположения мы будем использовать директиву try_files для проверки файлов, соответствующих отдельным запросам URI. Вместо того чтобы возвращать по умолчанию статус 404 Not Found​​​, мы будем передавать контроль файлу index.php Drupal с аргументами запроса.

      • location ~.php$: этот блок расположения будет обрабатывать PHP-запросы и проксировать эти запросы в наш контейнер drupal. Поскольку наш образ Drupal Docker будет опираться на образ php:fpm, мы также добавим параметры конфигурации, принадлежащие протоколу FastCGI, в этот блок. Nginx требует наличия независимого процессора PHP для запросов PHP: в нашем случае эти запросы будут обрабатываться процессором php-fpm, который будет включать образ php:fpm. Кроме того, этот блок расположения содержит директивы FastCGI, переменные и параметры, которые будут проксировать запросы для приложения Drupal, запущенного в нашем контейнере Drupal, задавать предпочитаемый индекс захваченного URI запроса, а также выполнять парсинг запросов URI.

      • location ~ /.ht: этот блок будет обрабатывать файлы .htaccess, поскольку Nginx не будет обслуживать их. Директива deny_all гарантирует, что файлы .htaccess никогда не будут отображаться для пользователей.

      • location = /favicon.ico, location = /robots.txt: эти блоки гарантируют, что запросы для /favicon.ico и /robots.txt не будут регистрироваться.

      • location ~* .(css|gif|ico|jpeg|jpg|js|png)$: этот блок отключает запись в журнал для запросов статичных активов и гарантирует, что эти активы будут иметь высокую кэшируемость, поскольку обычно их трудно обслуживать.

      Дополнительную информацию о проксировании FastCGI см. в статье Понимание и реализация проксирования FastCGI в Nginx. Информацию о серверных блоках и блоках расположения см. в статье Знакомство с сервером Nginx и алгоритмы выбора блоков расположения.

      Сохраните и закройте файл после завершения редактирования.

      После настройки конфигурации Nginx вы можете перейти к созданию переменных среды для передачи в контейнеры приложения и базы данных во время исполнения.

      Шаг 2 — Настройка переменных среды

      Для сохранения информации, связанной с сайтом, нашему приложению Drupal требуется база данных (MySQL, PostgresSQL и др.). Контейнеру Drupal потребуется доступ к определенным переменным среды во время исполнения, чтобы получить доступ к контейнеру базы данных (MySQL). Эти переменные содержат конфиденциальную информацию, например учетные данные базы данных, поэтому мы не можем раскрыть ее непосредственно в файле Docker Compose — главном файле, содержащем информацию о том, как будут работать наши контейнеры.

      Рекомендуется всегда помещать конфиденциальные значения в файл .env и ограничить их использование до внутреннего. Это не позволит скопировать эти значения в репозиторий нашего проекта и открыть их для общего доступа.

      В главной директории проекта ~/drupal, создайте и откройте файл .env:

      Добавьте в файл .env следующие переменные, заменив выделенные части на учетные данные, которые вы хотите использовать:

      ~/drupal/.env

      MYSQL_ROOT_PASSWORD=root_password
      MYSQL_DATABASE=drupal
      MYSQL_USER=drupal_database_user
      MYSQL_PASSWORD=drupal_database_password
      

      Теперь мы добавили пароль для административной учетной записи root MySQL, а также предпочитаемые имя пользователя и пароль для нашей базы данных приложения.

      Наш файл .env содержит конфиденциальную информацию, поэтому его всегда рекомендуется включать в файлы проекта .gitignore и .dockerignore, чтобы ее нельзя было добавить в наши репозитории Git и образы Docker.

      Если вы планируете использовать Git для контроля версий, инициализируйте текущую рабочую директорию в качестве репозитория с помощью git init:

      Откройте файл .gitignore:

      Добавьте следующее:

      ~/drupal/.gitignore

      .env
      

      Сохраните и закройте файл.

      Подобным образом откройте файл .dockerignore:

      Затем добавьте следующее:

      ~/drupal/.dockerignore

      .env
      .git
      

      Сохраните и закройте файл.

      Теперь, когда мы приняли меры для защиты наших учетных данных как переменных среды, перейдем к следующему шагу определения наших служб в файле docker-compose.yml.

      Шаг 3 — Определение служб с помощью Docker Compose

      Docker Compose — это инструмент для определения и запуска многоконтейнерных приложений. Мы определяем файл YAML для настройки служб нашего приложения. Служба Docker Compose — это запущенный контейнер, и Compose позволяет нам связывать эти службы с общими томами и сетями.

      Мы создадим разные контейнеры для нашего приложения, базы данных и веб-сервера Drupal. Также мы создадим контейнер для запуска Certbot​​​, чтобы получить сертификаты для нашего веб-сервера.

      Создайте файл docker-compose.yml:

      Добавьте следующий код для определения версии файла Compose и службы базы данных mysql:

      ~/drupal/docker-compose.yml

      version: "3"
      
      services:
        mysql:
          image: mysql:8.0
          container_name: mysql
          command: --default-authentication-plugin=mysql_native_password
          restart: unless-stopped
          env_file: .env
          volumes:
            - db-data:/var/lib/mysql
          networks:
            - internal
      

      Давайте пройдемся по ним отдельно со всеми параметрами настройки службы mysql​​​:

      • image: указывает образ, который будет использоваться/извлекаться для создания контейнера. Чтобы избежать конфликтов в будущем, рекомендуется всегда использовать образ с соответствующей версией тега, кроме тега latest. Подробнее об оптимальных методах использования Dockerfile узнайте в документации Docker.

      • container_name: определяет имя контейнера.

      • command: используется для отмены команды по умолчанию (инструкции CMD) в образе. MySQL поддерживает разные плагины аутентификации, но mysql_native_password — это традиционный способ аутентификации. Поскольку PHP и, следовательно, Drupal не будут поддерживать более новую аутентификацию MySQL, необходимо установить --default-authentication-plugin=mysql_native_password​​​ в качестве механизма аутентификации по умолчанию.

      • restart: используется для определения политики контейнера. Политика unless-stopped​​​ повторно запускает контейнер, пока он не будет остановлен вручную.

      • env_file: добавляет переменные среды из файла. В нашем случае он будет считывать переменные среды из файла .env, определенные в предыдущем шаге.

      • volumes: монтирует пути к хосту или томам с именем, указанным как подпараметры службы. Мы монтируем том с именем db-data в директорию /var/lib/mysql​​​ в контейнере, куда MySQL по умолчанию будет записывать свои файлы данных.

      • networks: определяет сеть internal, к которой подключится наша служба приложения. Мы определим сети в конце файла.

      Мы дали определение нашей службы mysql​​​, а теперь добавим определение службы приложения drupal в конец файла:

      ~/drupal/docker-compose.yml

      ...
        drupal:
          image: drupal:8.7.8-fpm-alpine
          container_name: drupal
          depends_on:
            - mysql
          restart: unless-stopped
          networks:
            - internal
            - external
          volumes:
            - drupal-data:/var/www/html
      

      В этом определении службы мы называем наш контейнер и определяем политику перезапуска, как уже делали это для службы mysql. Также мы добавляем в этот контейнер ряд параметров:

      • image: здесь мы используем образ Drupal 8.7.8-fpm-alpine. Этот образ содержит процессор php-fpm, для которого наш веб-сервер Nginx должен выполнять обработку PHP. Кроме того, мы используем образ alpine, полученный из проекта Alpine Linux, который уменьшит размер всего образа и рекомендуется в оптимальных методах использования Dockerfile. Drupal имеет несколько версий и образов, ознакомьтесь с ними в Dockerhub.

      • depends_on: используется для выражения зависимости между службами. Определение службы mysql как зависимости к нашему контейнеру drupal обеспечит создание контейнера drupal​​​ после контейнера mysql​​​ ​​​и поможет успешно запустить наше приложение.

      • networks: здесь мы добавили этот контейнер в сеть external​​​ вместе с сетью internal​​​. Таким образом доступ к службе mysql​​​ будет возможен только из контейнера drupal по сети internal, но при этом доступ других контейнеров по сети external​​​ к этому контейнеру будет сохранен.

      • volumes: мы монтируем том с именем drupal-data на точку монтирования /var/www/html, созданную образом Drupal. Использование тома с именем таким образом позволит разделить наш код приложения с другими контейнерами.

      Далее добавим определение службы Nginx после определения службы drupal:

      ~/drupal/docker-compose.yml

      ...
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      

      Мы снова присвоим имя нашему контейнеру и сделаем его зависимым от контейнера Drupal в отношении порядка запуска. Также мы используем образ alpine — образ Nginx 1.17.4-alpine.

      Это определение службы также включает следующие параметры:

      • ports: этот параметр открывает порт 80, чтобы активировать параметры конфигурации, определенные нами в файле nginx.conf в шаге 1.

      • volumes: здесь мы определяем том с именем и путь хоста:

        • drupal-data:/var/www/html​​​: этот параметр будет монтировать код нашего приложения Drupal в директорию /var/www/html​​​, директорию, которую мы задали в качестве корневой директории в нашем серверном блоке Nginx.
        • ./nginx-conf:/etc/nginx/conf.d: этот элемент будет монтировать директорию конфигурации Nginx на хост в соответствующую директорию в контейнере, гарантируя, что любые изменения, которые мы вносим в файлы на хосте, будут отражены в контейнере.
        • certbot-etc:/etc/letsencrypt​​​: этот элемент будет монтировать соответствующие сертификаты и ключи Let’s Encrypt для нашего домена в соответствующую директорию контейнера.
        • networks: мы определили сеть external​​​ только для того, чтобы этот контейнер мог обмениваться данными с контейнером drupal​​​, а не с контейнером mysql​​​.

      Наконец, мы добавим наше последнее определение для службы certbot​​​. Обязательно замените sammy@your_domain​​​ и your_domain на свой адрес эл. почты и доменное имя:

      ~/drupal/docker-compose.yml

      ...
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
      

      Это определение попросит Compose извлекать образ certbot/certbot из Docker Hub. Также оно использует тома с именем для обмена ресурсами с контейнером Nginx, включая доменные сертификаты и ключ в certbot-etc и код приложения в drupal-data​​​.

      Мы также использовали depends_on, чтобы убедиться, что контейнер certbot​​​ будет запущен после запуска службы webserver​​​.

      Мы не указали здесь networks​​, поскольку этот контейнер не будет обмениваться данными с какими-либо службами по сети. Это просто добавление доменных сертификатов и ключа, которые мы монтировали с помощью томов с именем.

      Также мы включили параметр command, указывающий субкоманду для запуска с используемой контейнером по умолчанию командой certbot. Клиент Certbot​​ поддерживает плагины для получения и установки сертификатов. Мы используем плагин webroot для получения сертификата путем включения certonly и --webroot в командную строку. Подробнее о плагине и дополнительных командах читайте в официальной документации Certbot.

      Под определением службы certbot добавьте определения сети и тома:

      ~/drupal/docker-compose.yml

      ...
      networks:
        external:
          driver: bridge
        internal:
          driver: bridge
      
      volumes:
        drupal-data:
        db-data:
        certbot-etc:
      

      Ключ верхнего уровня networks​​​ позволяет нам указывать, какие сети необходимо создать. networks обеспечивает коммуникацию между службами/контейнерами во всех портах, так как они находятся на одном и том же хосте демона Docker. Мы определили две сети, internal​​​ и external​​​, для защиты коммуникации между службами webserver​​​, drupal​​​ и mysql​​​.

      Ключ volumes используется для определения томов с именем drupal-data, db-data и certbot-etc​​​. Когда Docker создает тома, содержимое тома сохраняется в директории файловой системы хоста, /var/lib/docker/volumes/, а данным процессом управляет Docker. После этого содержимое каждого тома монтируется из этой директории в любой контейнер, использующий том. Таким образом мы можем делиться кодом и данными между контейнерами.

      Итоговый файл docker-compose.yml будет выглядеть примерно так:

      ~/drupal/docker-compose.yml

      version: "3"
      
      services:
        mysql:
          image: mysql:8.0
          container_name: mysql
          command: --default-authentication-plugin=mysql_native_password
          restart: unless-stopped
          env_file: .env
          volumes:
            - db-data:/var/lib/mysql
          networks:
            - internal
      
        drupal:
          image: drupal:8.7.8-fpm-alpine
          container_name: drupal
          depends_on:
            - mysql
          restart: unless-stopped
          networks:
            - internal
            - external
          volumes:
            - drupal-data:/var/www/html
      
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
      
      networks:
        external:
          driver: bridge
        internal:
          driver: bridge
      
      volumes:
        drupal-data:
        db-data:
        certbot-etc:
      

      Мы завершили определение наших служб. Далее запустим контейнер и протестируем наши запросы сертификата.

      Шаг 4 — Получение сертификатов SSL и учетных данных

      Мы можем запустить наши контейнеры с помощью команды docker-compose up, которая будет создавать и запускать наши контейнеры и службы в указанном нами порядке. Если наши запросы доменов будут выполнены успешно, мы увидим корректный статус выхода в нашем выводе и нужные сертификаты, установленные в папке /etc/letsencrypt/live на контейнере веб-сервера.

      Чтобы запустить контейнеры в фоновом режиме, используйте команду docker-compose up с флагом -d​​​:

      Вы увидите аналогичный вывод, подтверждающий, что ваши службы были успешно созданы:

      Output

      ... Creating mysql ... done Creating drupal ... done Creating webserver ... done Creating certbot ... done

      Проверьте статус служб с помощью команды docker-compose ps:

      Мы увидим службы mysql, drupal и webserver с State в значении Up​​​, а выход из certbot​​​ будет выполнен с сообщением о статусе 0:

      Output

      Name Command State Ports -------------------------------------------------------------------------- certbot certbot certonly --webroot ... Exit 0 drupal docker-php-entrypoint php-fpm Up 9000/tcp mysql docker-entrypoint.sh --def ... Up 3306/tcp, 33060/tcp webserver nginx -g daemon off; Up 0.0.0.0:80->80/tcp

      Если вы увидите любое значение, кроме Up в столбце State для служб mysql​​​, drupal​​​ или webserver, или любое сообщение о статусе выхода, отличающееся от 0, для контейнера certbot, проверьте журналы службы с помощью команды docker-compose logs:

      • docker-compose logs service_name

      Теперь мы можем проверить, что наши сертификаты установлены на контейнере webserver, с помощью команды docker-compose exec:

      • docker-compose exec webserver ls -la /etc/letsencrypt/live

      Результат будет выглядеть следующим образом:

      Output

      total 16 drwx------ 3 root root 4096 Oct 5 09:15 . drwxr-xr-x 9 root root 4096 Oct 5 09:15 .. -rw-r--r-- 1 root root 740 Oct 5 09:15 README drwxr-xr-x 2 root root 4096 Oct 5 09:15 your_domain

      Теперь, когда все работает успешно, мы можем изменить определение службы certbot, чтобы удалить флаг --staging​​.

      Откройте файл docker-compose.yml, найдите определение службы certbot и замените флаг --staging в параметрах команды на флаг --force-renewal, который будет указывать Certbot, что вы хотите запросить новый сертификат с теми же доменами, что и в уже существующем сертификате. Обновленное определение certbot​​​ будет выглядеть примерно следующим образом:

      ~/drupal/docker-compose.yml

      ...
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
      ...
      

      Нам необходимо снова запустить docker-compose up​​​ для воссоздания контейнера certbot​​​. Также мы будем использовать параметр --no-deps, чтобы сообщить Compose о том, что можно пропустить запуск службы webserver, поскольку она уже запущена:

      • docker-compose up --force-recreate --no-deps certbot

      Мы увидим вывод, указывающий, что запрос сертификата выполнен успешно:

      Output

      Recreating certbot ... done Attaching to certbot certbot | Saving debug log to /var/log/letsencrypt/letsencrypt.log certbot | Plugins selected: Authenticator webroot, Installer None certbot | Renewing an existing certificate certbot | Performing the following challenges: certbot | http-01 challenge for your_domain certbot | http-01 challenge for www.your_domain certbot | Using the webroot path /var/www/html for all unmatched domains. certbot | Waiting for verification... certbot | Cleaning up challenges certbot | IMPORTANT NOTES: certbot | - Congratulations! Your certificate and chain have been saved at: certbot | /etc/letsencrypt/live/your_domain/fullchain.pem certbot | Your key file has been saved at: certbot | /etc/letsencrypt/live/your_domain/privkey.pem certbot | Your cert will expire on 2020-01-03. To obtain a new or tweaked certbot | version of this certificate in the future, simply run certbot certbot | again. To non-interactively renew *all* of your certificates, run certbot | "certbot renew" certbot | - Your account credentials have been saved in your Certbot certbot | configuration directory at /etc/letsencrypt. You should make a certbot | secure backup of this folder now. This configuration directory will certbot | also contain certificates and private keys obtained by Certbot so certbot | making regular backups of this folder is ideal. certbot | - If you like Certbot, please consider supporting our work by: certbot | certbot | Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate certbot | Donating to EFF: https://eff.org/donate-le certbot | certbot exited with code 0

      Теперь после успешного создания сертификатов можно обновить нашу конфигурацию Nginx, чтобы включить SSL.

      Шаг 5 — Изменение конфигурации веб-сервера и определения службы

      После установки сертификатов SSL в Nginx нам нужно будет перенаправить все запросы HTTP в HTTPS. Также необходимо указать наш сертификат SSL и места расположения ключей, а также добавить параметры безопасности и заголовки.

      Поскольку вы будете воссоздавать службу webserver для включения этих нововведений, сейчас вы можете остановить ее работу:

      • docker-compose stop webserver

      Результат будет выглядеть следующим образом:

      Output

      Stopping webserver ... done

      Затем удалим ранее созданный файл конфигурации Nginx:

      Откройте другую версию файла:

      • nano nginx-conf/nginx.conf

      Добавьте следующий код в файл для перенаправления HTTP на HTTPS и добавления учетных данных, протоколов и заголовков безопасности SSL. Не забудьте заменить your_domain на свой собственный домен:

      ~/drupal/nginx-conf/nginx.conf

      server {
          listen 80;
          listen [::]:80;
      
          server_name your_domain www.your_domain;
      
          location ~ /.well-known/acme-challenge {
              allow all;
              root /var/www/html;
          }
      
          location / {
              rewrite ^ https://$host$request_uri? permanent;
          }
      }
      server {
          listen 443 ssl;
          listen [::]:443 ssl;
          server_name your_domain www.your_domain;
      
          index index.php index.html index.htm;
      
          root /var/www/html;
      
          server_tokens off;
      
          ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
          ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
      
          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-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
      
          location / {
              try_files $uri $uri/ /index.php$is_args$args;
          }
      
          rewrite ^/core/authorize.php/core/authorize.php(.*)$ /core/authorize.php$1;
      
          location ~ .php$ {
              try_files $uri =404;
              fastcgi_split_path_info ^(.+.php)(/.+)$;
              fastcgi_pass drupal: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;
          }
      }
      

      Блок сервера HTTP указывает плагин webroot для запросов обновления Certbot в директории .well-known/acme-challenge. Также он содержит директиву перезаписи, которая перенаправляет запросы HTTP в корневую директорию HTTPS.

      Блок сервера HTTPS активирует ssl и http2. Дополнительную информацию о том, как выполняется итерация HTTP/2 в протоколах HTTP и какие преимущества это может дать для повышения производительности веб-сайта, см. во вводной части руководства по настройке Nginx с поддержкой HTTP/2 в Ubuntu 18.04.

      Эти блоки активируют SSL, поскольку мы включили наш сертификат SSL и места расположения ключей, а также рекомендуемые заголовки. Эти заголовки позволят нам получить рейтинг А на SSL Labs​​​ и сайтах тестирования сервера Security Headers.

      Наши директивы root и index также расположены в этом блоке, равно как и остальные блоки расположения Drupal, описанные в шаге 1.

      Сохраните и закройте обновленный файл конфигурации Nginx.

      Прежде чем воссоздать контейнер webserver, необходимо добавить сопоставление порта 443 в наше определение службы webserver, поскольку мы активировали сертификаты SSL.

      Откройте файл docker-compose.yml:

      Сделайте следующие изменения в определении службы webserver:

      ~/drupal/docker-compose.yml

      ...
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
            - 443:443
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      ...
      

      После активации сертификатов SSL наш файл docker-compose.yml​​​ будет выглядеть следующим образом:

      ~/drupal/docker-compose.yml

      version: "3"
      
      services:
        mysql:
          image: mysql:8.0
          container_name: mysql
          command: --default-authentication-plugin=mysql_native_password
          restart: unless-stopped
          env_file: .env
          volumes:
            - db-data:/var/lib/mysql
          networks:
            - internal
      
        drupal:
          image: drupal:8.7.8-fpm-alpine
          container_name: drupal
          depends_on:
            - mysql
          restart: unless-stopped
          networks:
            - internal
            - external
          volumes:
            - drupal-data:/var/www/html
      
        webserver:
          image: nginx:1.17.4-alpine
          container_name: webserver
          depends_on:
            - drupal
          restart: unless-stopped
          ports:
            - 80:80
            - 443:443
          volumes:
            - drupal-data:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - external
      
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - drupal-data:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
      
      networks:
        external:
          driver: bridge
        internal:
          driver: bridge
      
      volumes:
        drupal-data:
        db-data:
        certbot-etc:
      

      Сохраните и закройте файл. Давайте воссоздадим службу webserver с нашей обновленной конфигурацией:

      • docker-compose up -d --force-recreate --no-deps webserver

      Результат будет выглядеть следующим образом:

      Output

      Recreating webserver ... done

      Проверьте службы с помощью команды docker-compose ps:

      Мы увидим службы mysql, drupal и webserver со значением Up​​​, а выход из certbot​​​​ будет выполнен с сообщением о статусе 0:

      Output

      Name Command State Ports -------------------------------------------------------------------------- certbot certbot certonly --webroot ... Exit 0 drupal docker-php-entrypoint php-fpm Up 9000/tcp mysql docker-entrypoint.sh --def ... Up 3306/tcp, 33060/tcp webserver nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp

      Теперь все наши службы запущены, и мы можем продолжить установку Drupal через веб-интерфейс.

      Шаг 6 — Завершение установки через веб-интерфейс

      Давайте выполним установку через веб-интерфейс Drupal.

      В браузере перейдите к домену сервера. Не забудьте заменить здесь your_domain на ваше доменное имя:

      https://your_domain
      

      Выберите язык:

      Страница выбора языка в веб-интерфейсе Drupal

      Нажмите Сохранить и продолжить. Мы перейдем на страницу Профиль установки. Drupal имеет несколько профилей, поэтому выберите стандартный профиль и нажмите Сохранить и продолжить.

      Страница выбора профиля в веб-интерфейсе Drupal

      После выбора профиля мы перейдем к странице Конфигурация базы данных. Выберите тип базы данных MySQL, MySQL, MariaDB, Percona Server или аналогичная и введите значения для Имя базы данных, имя пользователя и пароль из значений, соответствующих MYSQL_DATABASE, MYSQL_USER​​​ и MYSQL_PASSWORD, определенных соответственно в файле .env в шаге 2. Нажмите Расширенные параметры и установите значение Хост, соответствующее контейнеру службы mysql​​​. Нажмите Сохранить и продолжить.

      Страница настройки базы данных в веб-интерфейсе Drupal

      После настройки базы данных начнется установка модулей и тем Drupal по умолчанию:

      Страница установки сайта в веб-интерфейсе Drupal

      После установки сайта мы перейдем к странице настройки сайта Drupal для настройки имени сайта, электронной почты, имени пользователя, пароля и региональных параметров. Заполните информацию и нажмите Сохранить и продолжить:

      Страница настройки сайта в веб-интерфейсе Drupal

      После нажатия Сохранить и продолжить мы увидим страницу Добро пожаловать в Drupal​​​, которая показывает, что наш сайт Drupal готов и работает успешно.

      Страница Добро пожаловать в Drupal в веб-интерфейсе Drupal

      Теперь после завершения установки Drupal необходимо убедиться, что наши сертификаты SSL будут обновляться автоматически.

      Шаг 7 — Обновление сертификатов

      Сертификаты Let’s Encrypt действительны в течение 90 дней, поэтому нам нужно будет настроить процесс автоматического обновления, чтобы гарантировать, что сертификаты не окажутся просроченными. Один из способов — создание задания с помощью утилиты планирования cron. В нашем случае мы настроим задание для cron с помощью скрипта, который будет обновлять наши сертификаты и перезагружать конфигурацию Nginx.

      Давайте создадим файл ssl_renew.sh для обновления наших сертификатов:

      Добавьте следующий код. Не забудьте заменить имя директории на свой собственный non-root user:

      ~/drupal/ssl_renew.sh

      
      #!/bin/bash
      
      cd /home/sammy/drupal/
      /usr/local/bin/docker-compose -f docker-compose.yml run certbot renew --dry-run && 
      /usr/local/bin/docker-compose -f docker-compose.yml kill -s SIGHUP webserver
      

      Этот скрипт меняет директорию проекта ~/drupal и запускает следующие команды docker-compose.

      • docker-compose run: данный параметр запускает контейнер certbot и переопределяет параметр command, указанный в определении службы certbot. Вместо использования субкоманды certonly мы используем здесь субкоманду renew, которая будет обновлять сертификаты, срок действия которых близок к окончанию. Мы включили параметр --dry-run, чтобы протестировать наш скрипт.

      • docker-compose kill: данный параметр отправляет сигнал SIGHUP контейнеру webserver для перезагрузки конфигурации Nginx.

      Закройте файл и настройте его исполняемость, запустив следующую команду:

      • sudo chmod +x ssl_renew.sh

      Далее откройте root-файл crontab для запуска скрипта обновления с заданным интервалом:

      Если вы впервые редактируете файл, вас попросят выбрать текстовый редактор, чтобы открыть файл с его помощью:

      Output

      no crontab for root - using an empty one Select an editor. To change later, run 'select-editor'. 1. /bin/nano 2. /usr/bin/vim.basic 3. /usr/bin/vim.tiny 4. /bin/ed Choose 1-4 [1]: ...

      В конце файла добавьте следующую строку, заменив sammy на ваше имя пользователя:

      crontab

      ...
      */5 * * * * /home/sammy/drupal/ssl_renew.sh >> /var/log/cron.log 2>&1
      

      В результате будет установлен интервал в пять минут для выполнения работы, и мы сможем проверить, работает ли запрос обновления в соответствии с ожиданиями. Также мы создали файл журнала, cron.log, чтобы записывать соответствующий вывод выполнения задания.

      Через пять минут воспользуйтесь командой tail для проверки cron.log, чтобы увидеть, выполнен ли запрос обновления:

      • tail -f /var/log/cron.log

      Вы увидите вывод, подтверждающий успешное обновление:

      Output

      ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates below have not been saved.) Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/your_domain/fullchain.pem (success) ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates above have not been saved.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Нажмите CTRL+C, чтобы завершить процесс tail.

      Теперь мы можем изменить файл crontab для запуска скрипта каждый 2-й день недели в 2:00. Измените последнюю строку crontab на следующее:

      crontab

      ...
      * 2 * * 2 /home/sammy/drupal/ssl_renew.sh >> /var/log/cron.log 2>&1
      

      Закройте и сохраните файл.

      Теперь удалим параметр --dry-run из скрипта ssl_renew.sh. Сначала откройте его:

      Затем измените содержимое на следующее:

      ~/drupal/ssl_renew.sh

      #!/bin/bash
      
      cd /home/sammy/drupal/
      /usr/local/bin/docker-compose -f docker-compose.yml run certbot renew && 
      /usr/local/bin/docker-compose -f docker-compose.yml kill -s SIGHUP webserver
      

      Теперь наше задание cron будет выполнять обновление сертификатов SSL.

      Заключение

      В этом руководстве мы использовали Docker Compose для создания установки Drupal с веб-сервером Nginx. В рамках этого рабочего процесса мы получили сертификаты TLS/SSL для домена, который мы хотели ассоциировать с сайтом Drupal, и создали задание cron для обновления этих сертификатов при необходимости.

      Для получения дополнительной информации посетите тематическую страницу Docker.



      Source link