Einführung
Es gibt mehrere Möglichkeiten, die Flexibilität und Sicherheit IhrerNode.js-Anwendung zu verbessern. Die Verwendung vonreverse proxy wieNginx bietet Ihnen die Möglichkeit, Lastausgleichsanforderungen zu erstellen, statischen Inhalt zwischenzuspeichern undTransport Layer Security (TLS) zu implementieren. Durch Aktivieren von verschlüsseltem HTTPS auf Ihrem Server wird sichergestellt, dass die Kommunikation zu und von Ihrer Anwendung sicher bleibt.
Das Implementieren eines Reverse-Proxys mit TLS / SSL in Containern erfordert andere Verfahren als das direkte Arbeiten auf einem Host-Betriebssystem. Wenn Sie beispielsweise Zertifikate vonLet’s Encrypt für eine Anwendung erhalten, die auf einem Server ausgeführt wird, installieren Sie die erforderliche Software direkt auf Ihrem Host. Mit Containern können Sie einen anderen Ansatz wählen. MitDocker Compose können Sie Container für Ihre Anwendung, Ihren Webserver und dieCertbot client erstellen, mit denen Sie Ihre Zertifikate erhalten können. Wenn Sie diese Schritte ausführen, können Sie die Modularität und Portabilität eines containerisierten Workflows nutzen.
In diesem Lernprogramm stellen Sie eine Node.js-Anwendung mit einem Nginx-Reverseproxy mithilfe von Docker Compose bereit. Sie erhalten TLS / SSL-Zertifikate für die Ihrer Anwendung zugeordnete Domäne und stellen sicher, dass sie eine hohe Sicherheitsbewertung vonSSL Labs erhält. Schließlich richten Sie einencron
-Job ein, um Ihre Zertifikate zu erneuern, damit Ihre Domain sicher bleibt.
Voraussetzungen
Um diesem Tutorial zu folgen, benötigen Sie:
-
Ein Ubuntu 18.04-Server, ein Nicht-Root-Benutzer mit
sudo
-Berechtigungen und eine aktive Firewall. Anleitungen zum Einrichten finden Sie inInitial Server Setup guide. -
Docker und Docker Compose sind auf Ihrem Server installiert. Befolgen Sie die Schritte 1 und 2 vonHow To Install and Use Docker on Ubuntu 18.04, um Anleitungen zur Installation von Docker zu erhalten. Befolgen Sie die Anweisungen zur Installation von Compose in Schritt 1 vonHow To Install Docker Compose on Ubuntu 18.04.
-
Ein registrierter Domainname. In diesem Tutorial werden durchgehendexample.com verwendet. Sie können eine kostenlos beiFreenom erhalten oder den Domain-Registrar Ihrer Wahl verwenden.
-
Die beiden folgenden DNS-Einträge wurden für Ihren Server eingerichtet. Sie könnenthis introduction to DigitalOcean DNS folgen, um Details zum Hinzufügen zu einem DigitalOcean-Konto zu erhalten, wenn Sie dies verwenden:
-
Ein A-Datensatz mit
example.com
, der auf die öffentliche IP-Adresse Ihres Servers verweist. -
Ein A-Datensatz mit
www.example.com
, der auf die öffentliche IP-Adresse Ihres Servers verweist.
-
[[Schritt 1 - Klonen und Testen der Knotenanwendung]] == Schritt 1 - Klonen und Testen der Knotenanwendung
Als ersten Schritt klonen wir das Repository mit dem Node-Anwendungscode, der die Docker-Datei enthält, mit der wir unser Anwendungsimage mit Compose erstellen. Wir können die Anwendung zuerst testen, indem wir sie mitdocker run
command ohne Reverse Proxy oder SSL erstellen und ausführen.
Klonen Sie im Home-Verzeichnis Ihres Nicht-Root-Benutzers dienodejs-image-demo
repository aus denDigitalOcean Community GitHub account. Dieses Repository enthält den Code aus dem inHow To Build a Node.js Application with Docker beschriebenen Setup.
Klonen Sie das Repository in ein Verzeichnis namensnode_project
:
git clone https://github.com/do-community/nodejs-image-demo.git node_project
Wechseln Sie in das Verzeichnisnode_project
:
cd node_project
In diesem Verzeichnis befindet sich eine Docker-Datei, die Anweisungen zum Erstellen einer Knotenanwendung unter Verwendung derDocker node:10
image und des Inhalts Ihres aktuellen Projektverzeichnisses enthält. Sie können den Inhalt der Docker-Datei anzeigen, indem Sie Folgendes eingeben:
cat Dockerfile
OutputFROM node:10-alpine
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
RUN npm install
COPY --chown=node:node . .
EXPOSE 8080
CMD [ "node", "app.js" ]
Diese Anweisungen erstellen ein Knotenabbild, indem Sie den Projektcode aus dem aktuellen Verzeichnis in den Container kopieren und Abhängigkeiten mitnpm install
installieren. Sie nutzen auch Dockerscaching and image layering, indem sie die Kopie vonpackage.json
undpackage-lock.json
, die die aufgelisteten Abhängigkeiten des Projekts enthält, von der Kopie des restlichen Anwendungscodes trennen. Schließlich geben die Anweisungen an, dass der Container als Nicht-Root-Benutzernodemit den entsprechenden Berechtigungen ausgeführt wird, die für den Anwendungscode und die Verzeichnissenode_modules
festgelegt wurden.
Weitere Informationen zu diesen Best Practices für Dockerfile- und Node-Images finden Sie in der vollständigen Diskussion inStep 3 of How To Build a Node.js Application with Docker.
Um die Anwendung ohne SSL zu testen, können Sie das Image mitdocker build
und dem Flag-t
erstellen und kennzeichnen. Wir werden das Bildnode-demo
nennen, aber Sie können es auch anders benennen:
docker build -t node-demo .
Sobald der Erstellungsprozess abgeschlossen ist, können Sie Ihre Bilder mitdocker images
auflisten:
docker images
Sie sehen die folgende Ausgabe, die die Erstellung des Anwendungsimages bestätigt:
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
node-demo latest 23961524051d 7 seconds ago 73MB
node 10-alpine 8a752d5af4ce 3 weeks ago 70.7MB
Erstellen Sie als Nächstes den Container mitdocker run
. Wir werden drei Flags in diesen Befehl aufnehmen:
-
-p
: Dies veröffentlicht den Port auf dem Container und ordnet ihn einem Port auf unserem Host zu. Wir werden Port80
auf dem Host verwenden, aber Sie können dies nach Bedarf ändern, wenn auf diesem Port ein anderer Prozess ausgeführt wird. Weitere Informationen zur Funktionsweise finden Sie in dieser Diskussion in den Docker-Dokumenten zuport binding. -
-d
: Hiermit wird der Container im Hintergrund ausgeführt. -
--name
: Dadurch können wir dem Container einen einprägsamen Namen geben.
Führen Sie den folgenden Befehl aus, um den Container zu erstellen:
docker run --name node-demo -p 80:8080 -d node-demo
Überprüfen Sie Ihre laufenden Container mitdocker ps
:
docker ps
Sie sehen die Ausgabe, die bestätigt, dass Ihr Anwendungscontainer ausgeführt wird:
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4133b72391da node-demo "node app.js" 17 seconds ago Up 16 seconds 0.0.0.0:80->8080/tcp node-demo
Sie können jetzt Ihre Domain besuchen, um Ihr Setup zu testen:http://example.com
. Denken Sie daran,example.com
durch Ihren eigenen Domainnamen zu ersetzen. Ihre Anwendung zeigt die folgende Zielseite an:
Nachdem Sie die Anwendung getestet haben, können Sie den Container anhalten und die Bilder entfernen. Verwenden Sie erneutdocker ps
, um IhreCONTAINER ID
zu erhalten:
docker ps
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4133b72391da node-demo "node app.js" 17 seconds ago Up 16 seconds 0.0.0.0:80->8080/tcp node-demo
Stoppen Sie den Container mitdocker stop
. Stellen Sie sicher, dass Sie die hier aufgeführtenCONTAINER ID
durch Ihre eigene AnwendungCONTAINER ID
ersetzen:
docker stop 4133b72391da
Sie können jetzt den gestoppten Container und alle Bilder, einschließlich nicht verwendeter und baumelnder Bilder, mitdocker system prune
und dem Flag-a
entfernen:
docker system prune -a
Geben Siey
ein, wenn Sie in der Ausgabe dazu aufgefordert werden, zu bestätigen, dass Sie den gestoppten Container und die angehaltenen Bilder entfernen möchten. Beachten Sie, dass dadurch auch der Build-Cache gelöscht wird.
Nachdem Sie Ihr Anwendungsimage getestet haben, können Sie den Rest Ihres Setups mit Docker Compose erstellen.
[[Schritt 2 - Definieren der Webserverkonfiguration] == Schritt 2 - Definieren der Webserverkonfiguration
Mit unserer Anwendung Dockerfile können wir eine Konfigurationsdatei erstellen, um unseren Nginx-Container auszuführen. Wir beginnen mit einer minimalen Konfiguration, die unseren Domänennamen,document root, Proxy-Informationen und einen Standortblock enthält, um die Anforderungen von Certbot an das Verzeichnis.well-known
zu leiten, wo eine temporäre Datei abgelegt wird, um dies zu überprüfen Das DNS für unsere Domain wird auf unserem Server aufgelöst.
Erstellen Sie zunächst im aktuellen Projektverzeichnis ein Verzeichnis für die Konfigurationsdatei:
mkdir nginx-conf
Öffnen Sie die Datei mitnano
oder Ihrem bevorzugten Editor:
nano nginx-conf/nginx.conf
Fügen Sie den folgenden Serverblock hinzu, um Proxy-Benutzeranforderungen an Ihren Knotenanwendungscontainer zu senden und die Anforderungen von Certbot an das Verzeichnis.well-known
weiterzuleiten. Stellen Sie sicher, dass Sieexample.com
durch Ihren eigenen Domainnamen ersetzen:
~/node_project/nginx-conf/nginx.conf
server {
listen 80;
listen [::]:80;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
proxy_pass http://nodejs:8080;
}
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
}
Mit diesem Serverblock können wir den Nginx-Container als Reverse-Proxy starten, der Anforderungen an unseren Node-Anwendungscontainer weiterleitet. Außerdem können wir diewebroot pluginvon Certbot verwenden, um Zertifikate für unsere Domain zu erhalten. Dieses Plugin hängt vonHTTP-01 validation methodab, das mithilfe einer HTTP-Anforderung nachweist, dass Certbot von einem Server, der auf einen bestimmten Domänennamen reagiert, auf Ressourcen zugreifen kann.
Speichern und schließen Sie die Datei, nachdem Sie die Bearbeitung abgeschlossen haben. Weitere Informationen zu Nginx-Server- und Standortblockierungsalgorithmen finden Sie in diesem Artikel zuUnderstanding Nginx Server and Location Block Selection Algorithms.
Mit den Konfigurationsdetails des Webservers können wir mit der Erstellung unsererdocker-compose.yml
-Datei fortfahren, mit der wir unsere Anwendungsdienste und den Certbot-Container erstellen können, mit dem wir unsere Zertifikate erhalten.
[[Schritt-3 -—- Erstellen der Docker-Compose-Datei]] == Schritt 3 - Erstellen der Docker-Compose-Datei
Die Dateidocker-compose.yml
definiert unsere Dienste, einschließlich der Knotenanwendung und des Webservers. Es werden Details wie benannte Volumes angegeben, die für die gemeinsame Nutzung von SSL-Anmeldeinformationen zwischen Containern sowie für Netzwerk- und Portinformationen von entscheidender Bedeutung sind. Außerdem können wir bestimmte Befehle angeben, die beim Erstellen unserer Container ausgeführt werden sollen. Diese Datei ist die zentrale Ressource, die definiert, wie unsere Services zusammenarbeiten.
Öffnen Sie die Datei in Ihrem aktuellen Verzeichnis:
nano docker-compose.yml
Definieren Sie zunächst den Anwendungsservice:
~/node_project/docker-compose.yml
version: '3'
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
Die Service-Definition vonnodejs
umfasst Folgendes:
-
build
: Hiermit werden die Konfigurationsoptionen definiert, einschließlichcontext
unddockerfile
, die beim Erstellen des Anwendungsabbilds durch Compose angewendet werden. Wenn Sie ein vorhandenes Image aus einer Registrierung wieDocker Hub verwenden möchten, können Sie stattdessenimage
instruction mit Informationen zu Ihrem Benutzernamen, Repository und Image-Tag verwenden. -
context
: Dies definiert den Build-Kontext für den Build des Anwendungsimages. In diesem Fall ist es das aktuelle Projektverzeichnis. -
dockerfile
: Dies gibt die Docker-Datei an, die Compose für den Build verwendet - die Docker-Datei, die Sie inStep 1 betrachtet haben. -
image
,container_name
: Diese wenden Namen auf das Bild und den Container an. -
restart
: Dies definiert die Neustartrichtlinie. Der Standardwert istno
, aber wir haben den Container so eingestellt, dass er neu gestartet wird, sofern er nicht gestoppt wird.
Beachten Sie, dass wir Bindmounts nicht in diesen Service einbeziehen, da sich unser Setup eher auf die Bereitstellung als auf die Entwicklung konzentriert. Weitere Informationen finden Sie in der Docker-Dokumentation zubind mounts undvolumes.
Um die Kommunikation zwischen der Anwendung und den Webserver-Containern zu ermöglichen, fügen wir unterhalb der Neustartdefinition ein Brückennetzwerk mit dem Namenapp-network
hinzu:
~/node_project/docker-compose.yml
services:
nodejs:
...
networks:
- app-network
Ein solches benutzerdefiniertes Bridge-Netzwerk ermöglicht die Kommunikation zwischen Containern auf demselben Docker-Daemon-Host. Dies rationalisiert den Verkehr und die Kommunikation in Ihrer Anwendung, da alle Ports zwischen Containern im selben Brückennetz geöffnet werden und keine Ports für die Außenwelt freigegeben werden. Auf diese Weise können Sie gezielt nur die Ports öffnen, die Sie zum Anzeigen Ihrer Frontend-Services benötigen.
Definieren Sie als Nächstes den Dienst vonwebserver
:
~/node_project/docker-compose.yml
...
webserver:
image: nginx:mainline-alpine
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- web-root:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
depends_on:
- nodejs
networks:
- app-network
Einige der Einstellungen, die wir für den Dienstnodejs
definiert haben, bleiben unverändert, wir haben jedoch auch die folgenden Änderungen vorgenommen:
-
image
: Hiermit wird Compose angewiesen, die neuestenAlpine-basedNginx image vom Docker Hub abzurufen. Weitere Informationen zualpine
Bildern finden Sie in Schritt 3 vonHow To Build a Node.js Application with Docker. -
ports
: Dadurch wird Port80
verfügbar gemacht, um die Konfigurationsoptionen zu aktivieren, die wir in unserer Nginx-Konfiguration definiert haben.
Wir haben auch die folgenden benannten Volumes und Bindungs-Mounts angegeben:
-
web-root:/var/www/html
: Hiermit werden die statischen Assets unserer Site, die auf ein Volume namensweb-root
kopiert wurden, zum Verzeichnis/var/www/html
im Container hinzugefügt. -
./nginx-conf:/etc/nginx/conf.d
: Dadurch wird das Nginx-Konfigurationsverzeichnis auf dem Host an das entsprechende Verzeichnis im Container gebunden, um sicherzustellen, dass alle Änderungen, die wir an Dateien auf dem Host vornehmen, im Container berücksichtigt werden. -
certbot-etc:/etc/letsencrypt
: Dadurch werden die relevanten Let's Encrypt-Zertifikate und -Schlüssel für unsere Domain in das entsprechende Verzeichnis im Container gemountet. -
certbot-var:/var/lib/letsencrypt
: Hiermit wird das Standardarbeitsverzeichnis von Let's Encrypt in das entsprechende Verzeichnis im Container eingefügt.
Fügen Sie als Nächstes die Konfigurationsoptionen für den Containercertbot
hinzu. Achten Sie darauf, die Domain- und E-Mail-Informationen durch Ihren eigenen Domainnamen und Ihre Kontakt-E-Mail-Adresse zu ersetzen:
~/node_project/docker-compose.yml
...
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- web-root:/var/www/html
depends_on:
- webserver
command: certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --staging -d example.com -d www.example.com
Diese Definition weist Compose an, diecertbot/certbot image von Docker Hub abzurufen. Außerdem werden benannte Volumes verwendet, um Ressourcen für den Nginx-Container freizugeben, einschließlich der Domänenzertifikate und des Schlüssels incertbot-etc
, des Arbeitsverzeichnisses Let's Encrypt incertbot-var
und des Anwendungscodes inweb-root
.
Wiederum haben wirdepends_on
verwendet, um anzugeben, dass der Containercertbot
gestartet werden soll, sobald der Dienstwebserver
ausgeführt wird.
Wir haben auch die Optioncommand
hinzugefügt, die den Befehl angibt, der beim Starten des Containers ausgeführt werden soll. Es enthält den Unterbefehlcertonly
mit den folgenden Optionen:
-
--webroot
: Hiermit wird Certbot angewiesen, das Webroot-Plugin zu verwenden, um Dateien zur Authentifizierung im Webroot-Ordner abzulegen. -
--webroot-path
: Gibt den Pfad des Webroot-Verzeichnisses an. -
--email
: Ihre bevorzugte E-Mail-Adresse für die Registrierung und Wiederherstellung. -
--agree-tos
: Dies gibt an, dass SieACME’s Subscriber Agreement zustimmen. -
--no-eff-email
: Hiermit wird Certbot mitgeteilt, dass Sie Ihre E-Mail nicht mitElectronic Frontier Foundation (EFF) teilen möchten. Fühlen Sie sich frei, dies wegzulassen, wenn Sie es vorziehen würden. -
--staging
: Hiermit wird Certbot mitgeteilt, dass Sie die Staging-Umgebung von Let's Encrypt verwenden möchten, um Testzertifikate zu erhalten. Mit dieser Option können Sie Ihre Konfigurationsoptionen testen und mögliche Beschränkungen für Domänenanforderungen vermeiden. Weitere Informationen zu diesen Grenzwerten finden Sie unter Let's Encrypt'srate limits documentation. -
-d
: Hier können Sie Domainnamen angeben, die Sie auf Ihre Anfrage anwenden möchten. In diesem Fall haben wirexample.com
undwww.example.com
eingeschlossen. Stellen Sie sicher, dass Sie diese durch Ihre eigenen Domain-Einstellungen ersetzen.
Fügen Sie als letzten Schritt die Volume- und Netzwerkdefinitionen hinzu. Stellen Sie sicher, dass Sie den Benutzernamen hier durch Ihren eigenen Benutzer ohne Rootberechtigung ersetzen:
~/node_project/docker-compose.yml
...
volumes:
certbot-etc:
certbot-var:
web-root:
driver: local
driver_opts:
type: none
device: /home/sammy/node_project/views/
o: bind
networks:
app-network:
driver: bridge
Zu unseren benannten Volumes gehören unser Certbot-Zertifikat und die Arbeitsverzeichnis-Volumes sowie das Volume für die statischen Assets unserer Site,web-root
. In den meisten Fällen ist der Standardtreiber für Docker-Volumes derlocal
-Treiber, der unter Linux ähnliche Optionen wiemount
command akzeptiert. Dank dessen können wir eine Liste von Treiberoptionen mitdriver_opts
angeben, die das Verzeichnisviews
auf dem Host, der die statischen Assets unserer Anwendung enthält, zur Laufzeit auf dem Volume bereitstellen. Der Verzeichnisinhalt kann dann zwischen Containern geteilt werden. Weitere Informationen zum Inhalt des Verzeichnissesviews
finden Sie unterStep 2 of How To Build a Node.js Application with Docker.
Die Dateidocker-compose.yml
ieht nach Abschluss folgendermaßen aus:
~/node_project/docker-compose.yml
version: '3'
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
networks:
- app-network
webserver:
image: nginx:mainline-alpine
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- web-root:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
depends_on:
- nodejs
networks:
- app-network
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- web-root:/var/www/html
depends_on:
- webserver
command: certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --staging -d example.com -d www.example.com
volumes:
certbot-etc:
certbot-var:
web-root:
driver: local
driver_opts:
type: none
device: /home/sammy/node_project/views/
o: bind
networks:
app-network:
driver: bridge
Mit den vorhandenen Dienstdefinitionen können Sie die Container starten und Ihre Zertifikatanforderungen testen.
[[Schritt 4 - Abrufen von SSL-Zertifikaten und Anmeldeinformationen]] == Schritt 4 - Abrufen von SSL-Zertifikaten und Anmeldeinformationen
Wir können unsere Container mitdocker-compose up
starten, wodurch unsere Container und Services in der von uns angegebenen Reihenfolge erstellt und ausgeführt werden. Wenn unsere Domain-Anfragen erfolgreich sind, sehen wir den korrekten Exit-Status in unserer Ausgabe und die richtigen Zertifikate im Ordner/etc/letsencrypt/live
auf dem Containerwebserver
.
Erstellen Sie die Services mitdocker-compose up
und dem Flag-d
, wodurch die Containernodejs
undwebserver
im Hintergrund ausgeführt werden:
docker-compose up -d
Sie sehen die Ausgabe, die bestätigt, dass Ihre Services erstellt wurden:
OutputCreating nodejs ... done
Creating webserver ... done
Creating certbot ... done
Überprüfen Sie mitdocker-compose ps
den Status Ihrer Dienste:
docker-compose ps
Wenn alles erfolgreich war, sollten Ihre Dienstenodejs
undwebserver
Up
sein, und der Containercertbot
wurde mit der Statusmeldung0
beendet:
Output Name Command State Ports
------------------------------------------------------------------------
certbot certbot certonly --webroot ... Exit 0
nodejs node app.js Up 8080/tcp
webserver nginx -g daemon off; Up 0.0.0.0:80->80/tcp
Wenn Sie in der SpalteState
für die Dienstenodejs
undwebserver
etwas anderes alsUp
oder fürcertbot
einen anderen Exit-Status als0
sehen ) s Container, überprüfen Sie die Serviceprotokolle mit dem Befehldocker-compose logs
:
docker-compose logs service_name
Sie können jetzt überprüfen, ob Ihre Anmeldeinformationen mitdocker-compose exec
im Containerwebserver
bereitgestellt wurden:
docker-compose exec webserver ls -la /etc/letsencrypt/live
Wenn Ihre Anfrage erfolgreich war, sehen Sie die Ausgabe wie folgt:
Outputtotal 16
drwx------ 3 root root 4096 Dec 23 16:48 .
drwxr-xr-x 9 root root 4096 Dec 23 16:48 ..
-rw-r--r-- 1 root root 740 Dec 23 16:48 README
drwxr-xr-x 2 root root 4096 Dec 23 16:48 example.com
Nachdem Sie wissen, dass Ihre Anforderung erfolgreich ist, können Sie die Dienstdefinition voncertbot
bearbeiten, um das Flag von--staging
zu entfernen.
Öffnen Siedocker-compose.yml
:
nano docker-compose.yml
Suchen Sie den Abschnitt der Datei mit der Dienstdefinitioncertbot
und ersetzen Sie das Flag--staging
in der Optioncommand
durch das Flag--force-renewal
, das Certbot mitteilt, dass Sie dies möchten Fordern Sie ein neues Zertifikat mit denselben Domänen wie ein vorhandenes Zertifikat an. Die Service-Definition voncertbot
ollte nun folgendermaßen aussehen:
~/node_project/docker-compose.yml
...
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- web-root:/var/www/html
depends_on:
- webserver
command: certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com
...
Sie können jetztdocker-compose up
ausführen, um dencertbot
-Container und seine relevanten Volumes neu zu erstellen. Wir werden auch die Option--no-deps
einfügen, um Compose mitzuteilen, dass das Starten des Diensteswebserver
übersprungen werden kann, da er bereits ausgeführt wird:
docker-compose up --force-recreate --no-deps certbot
In der Ausgabe wird angezeigt, dass Ihre Zertifikatanforderung erfolgreich war:
Outputcertbot | IMPORTANT NOTES:
certbot | - Congratulations! Your certificate and chain have been saved at:
certbot | /etc/letsencrypt/live/example.com/fullchain.pem
certbot | Your key file has been saved at:
certbot | /etc/letsencrypt/live/example.com/privkey.pem
certbot | Your cert will expire on 2019-03-26. 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
Wenn Ihre Zertifikate vorhanden sind, können Sie Ihre Nginx-Konfiguration so ändern, dass sie SSL enthält.
[[Schritt 5 - Ändern der Webserverkonfiguration und der Dienstdefinition] == Schritt 5 - Ändern der Webserverkonfiguration und der Dienstdefinition
Wenn Sie SSL in unserer Nginx-Konfiguration aktivieren, müssen Sie eine HTTP-Umleitung zu HTTPS hinzufügen und unser SSL-Zertifikat und die Schlüsselpositionen angeben. Dazu gehört auch die Angabe unserer Diffie-Hellman-Gruppe, die wir fürPerfect Forward Secrecy verwenden.
Da Sie den Dienstwebserver
neu erstellen, um diese Ergänzungen einzuschließen, können Sie ihn jetzt beenden:
docker-compose stop webserver
Erstellen Sie als Nächstes ein Verzeichnis in Ihrem aktuellen Projektverzeichnis für Ihren Diffie-Hellman-Schlüssel:
mkdir dhparam
Generieren Sie Ihren Schlüssel mitopenssl
command:
sudo openssl dhparam -out /home/sammy/node_project/dhparam/dhparam-2048.pem 2048
Es dauert einige Augenblicke, bis der Schlüssel generiert ist.
Um die relevanten Diffie-Hellman- und SSL-Informationen zu Ihrer Nginx-Konfiguration hinzuzufügen, entfernen Sie zunächst die zuvor erstellte Nginx-Konfigurationsdatei:
rm nginx-conf/nginx.conf
Ö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-Anmeldeinformationen, Protokolle und Sicherheitsheader hinzuzufügen. Denken Sie daran,example.com
durch Ihre eigene Domain zu ersetzen:
~/node_project/nginx-conf/nginx.conf
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
try_files $uri @nodejs;
}
location @nodejs {
proxy_pass http://nodejs:8080;
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;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
}
Der HTTP-Serverblock gibt die Webroot für Certbot-Erneuerungsanforderungen an das Verzeichnis.well-known/acme-challenge
an. Es enthält auch einrewrite directive, das HTTP-Anforderungen an das Stammverzeichnis an HTTPS weiterleitet.
Der HTTPS-Serverblock aktiviertssl
undhttp2
. Weitere Informationen darüber, wie HTTP / 2 in HTTP-Protokollen iteriert und welche Vorteile es für die Leistung der Website haben kann, finden Sie in der Einführung zuHow To Set Up Nginx with HTTP/2 Support on Ubuntu 18.04. Dieser Block enthält auch eine Reihe von Optionen, um sicherzustellen, dass Sie die aktuellsten SSL-Protokolle und -Verschlüsselungen verwenden und die OSCP-Heftung aktiviert ist. Mit dem OSCP-Heften können Sie während der erstenTLS handshake eine Antwort mit Zeitstempel voncertificate authority anbieten, wodurch der Authentifizierungsprozess beschleunigt werden kann.
Der Block gibt auch Ihre SSL- und Diffie-Hellman-Anmeldeinformationen und die Schlüsselpositionen an.
Schließlich haben wir die Proxy-Pass-Informationen in diesen Block verschoben, einschließlich eines Standortblocks mit der Anweisungtry_files
, der Anforderungen an unseren Alias-Node.js-Anwendungscontainer verweist, und eines Standortblocks für diesen Alias, der Sicherheitsheader enthält Auf diese Weise können wirA Bewertungen für Dinge wie die ServertestseitenSSL Labs undSecurity Headerserhalten. Diese Überschriften umfassenX-Frame-Options
,X-Content-Type-Options
,Referrer Policy
,Content-Security-Policy
undX-XSS-Protection
. Der HeaderHTTP Strict Transport Security
(HSTS) ist auskommentiert. Aktivieren Sie diese Option nur, wenn Sie die Auswirkungen verstanden und die“preload” functionality bewertet haben.
Speichern und schließen Sie die Datei, nachdem Sie die Bearbeitung abgeschlossen haben.
Bevor Sie den Dienstwebserver
neu erstellen, müssen Sie der Dienstdefinition in Ihrerdocker-compose.yml
-Datei einige Dinge hinzufügen, einschließlich relevanter Portinformationen für HTTPS und einer Diffie-Hellman-Datenträgerdefinition.
Öffne die Datei:
nano docker-compose.yml
Fügen Sie in der Dienstdefinition vonwebserver
die folgende Portzuordnung und das benannte Volume vondhparam
hinzu:
~/node_project/docker-compose.yml
...
webserver:
image: nginx:latest
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- web-root:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- dhparam:/etc/ssl/certs
depends_on:
- nodejs
networks:
- app-network
Fügen Sie als Nächstes das Volumen vondhparam
zu den Definitionen vonvolumes
hinzu:
~/node_project/docker-compose.yml
...
volumes:
...
dhparam:
driver: local
driver_opts:
type: none
device: /home/sammy/node_project/dhparam/
o: bind
Ähnlich wie das Volume vonweb-root
wird auf dem Volume vondhparam
der auf dem Host gespeicherte Diffie-Hellman-Schlüssel in den Container vonwebserver
eingehängt.
Speichern und schließen Sie die Datei, wenn Sie mit der Bearbeitung fertig sind.
Erstellen Sie den Dienstwebserver
neu:
docker-compose up -d --force-recreate --no-deps webserver
Überprüfen Sie Ihre Dienste mitdocker-compose ps
:
docker-compose ps
Die Ausgabe sollte anzeigen, dass Ihre Dienstenodejs
undwebserver
ausgeführt werden:
Output Name Command State Ports
----------------------------------------------------------------------------------------------
certbot certbot certonly --webroot ... Exit 0
nodejs node app.js Up 8080/tcp
webserver nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
Schließlich können Sie Ihre Domain besuchen, um sicherzustellen, dass alles wie erwartet funktioniert. Navigieren Sie in Ihrem Browser zuhttps://example.com
, und ersetzen Sieexample.com
durch Ihren eigenen Domainnamen. Sie sehen die folgende Zielseite:
Sie sollten auch das Schlosssymbol in der Sicherheitsanzeige Ihres Browsers sehen. Wenn Sie möchten, können Sie zuSSL Labs Server Test landing page oderSecurity Headers server test landing page navigieren. Mit den von uns enthaltenen Konfigurationsoptionen sollte Ihre Site für beide eine Bewertung vonAerhalten.
[[Schritt 6 - Erneuern von Zertifikaten]] == Schritt 6 - Erneuern von Zertifikaten
Let 's Encrypt-Zertifikate sind 90 Tage gültig. Sie sollten daher einen automatischen Erneuerungsprozess einrichten, um sicherzustellen, dass sie nicht verfallen. Eine Möglichkeit, dies zu tun, besteht darin, einen Job mit dem Planungsdienstprogrammcron
zu erstellen. In diesem Fall planen wir einencron
-Job mithilfe eines Skripts, das unsere Zertifikate erneuert und unsere Nginx-Konfiguration neu lädt.
Öffnen Sie ein Skript namensssl_renew.sh
in Ihrem Projektverzeichnis:
nano ssl_renew.sh
Fügen Sie dem Skript den folgenden Code hinzu, um Ihre Zertifikate zu erneuern und Ihre Webserverkonfiguration neu zu laden:
~/node_project/ssl_renew.sh
#!/bin/bash
/usr/local/bin/docker-compose -f /home/sammy/node_project/docker-compose.yml run certbot renew --dry-run \
&& /usr/local/bin/docker-compose -f /home/sammy/node_project/docker-compose.yml kill -s SIGHUP webserver
Zusätzlich zur Angabe des Speicherorts unsererdocker-compose
-Binärdatei geben wir auch den Speicherort unsererdocker-compose.yml
-Datei an, umdocker-compose
-Befehle auszuführen. In diesem Fall verwenden wirdocker-compose run
, um einencertbot
-Container zu starten und die in unserer Service-Definition angegebenencommand
mit einem anderen zu überschreiben: dem Unterbefehlrenew
, mit dem Zertifikate erneuert werden das sind kurz vor dem Ablauf. Wir haben hier die Option--dry-run
eingefügt, um unser Skript zu testen.
Das Skript verwendet danndocker-compose kill
, umSIGHUP
signal an den Containerwebserver
zu senden und die Nginx-Konfiguration neu zu laden. Weitere Informationen zur Verwendung dieses Prozesses zum Neuladen Ihrer Nginx-Konfiguration finden Sie unterthis Docker blog post on deploying the official Nginx image with Docker.
Schließen Sie die Datei, wenn Sie mit der Bearbeitung fertig sind. Mach es ausführbar:
chmod +x ssl_renew.sh
Öffnen Sie als Nächstes Ihrerootcrontab
-Datei, um das Erneuerungsskript in einem bestimmten Intervall auszuführen:
sudo crontab -e
Wenn Sie diese Datei zum ersten Mal bearbeiten, werden Sie aufgefordert, einen Editor auszuwählen:
crontab
no crontab for root - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/ed
2. /bin/nano <---- easiest
3. /usr/bin/vim.basic
4. /usr/bin/vim.tiny
Choose 1-4 [2]:
...
Fügen Sie am Ende der Datei die folgende Zeile hinzu:
crontab
...
*/5 * * * * /home/sammy/node_project/ssl_renew.sh >> /var/log/cron.log 2>&1
Dadurch wird das Auftragsintervall auf alle fünf Minuten festgelegt, sodass Sie testen können, ob Ihre Erneuerungsanforderung wie beabsichtigt funktioniert hat. Wir haben auch eine Protokolldateicron.log
erstellt, um relevante Ausgaben des Jobs aufzuzeichnen.
Überprüfen Sie nach fünf Minutencron.log
, um festzustellen, ob die Erneuerungsanforderung erfolgreich war oder nicht:
tail -f /var/log/cron.log
Sie sollten sehen, dass die Ausgabe 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/example.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Killing webserver ... done
Sie können jetzt diecrontab
-Datei ändern, um ein tägliches Intervall festzulegen. Um das Skript beispielsweise jeden Tag mittags auszuführen, müssen Sie die letzte Zeile der Datei folgendermaßen ändern:
crontab
...
0 12 * * * /home/sammy/node_project/ssl_renew.sh >> /var/log/cron.log 2>&1
Sie möchten auch die Option--dry-run
aus Ihremssl_renew.sh
-Skript entfernen:
~/node_project/ssl_renew.sh
#!/bin/bash
/usr/local/bin/docker-compose -f /home/sammy/node_project/docker-compose.yml run certbot renew \
&& /usr/local/bin/docker-compose -f /home/sammy/node_project/docker-compose.yml kill -s SIGHUP webserver
Durch den Job voncron
wird sichergestellt, dass Ihre Let's Encrypt-Zertifikate nicht verfallen, indem Sie sie erneuern, wenn sie berechtigt sind. Sie können auchset up log rotation with the Logrotate utility verwenden, um Ihre Protokolldateien zu drehen und zu komprimieren.
Fazit
Sie haben Container verwendet, um eine Node-Anwendung mit einem Nginx-Reverse-Proxy einzurichten und auszuführen. Sie haben auch SSL-Zertifikate für die Domäne Ihrer Anwendung gesichert und einencron
-Job eingerichtet, um diese Zertifikate bei Bedarf zu erneuern.
Wenn Sie mehr über Let's Encrypt-Plugins erfahren möchten, lesen Sie bitte unsere Artikel zur Verwendung vonNginx plugin oderstandalone plugin.
Weitere Informationen zu Docker Compose finden Sie in den folgenden Ressourcen:
DasCompose documentation ist auch eine großartige Ressource, um mehr über Anwendungen mit mehreren Containern zu erfahren.