如何使用 Nginx、Let's Encrypt 和 Docker Compose 保护容器化 Node.js 应用程序

2023-11-19

介绍

有多种方法可以增强您的灵活性和安全性Node.js应用。用一个反向代理 like Nginx为您提供负载平衡请求、缓存静态内容和实施传输层安全(TLS)。在服务器上启用加密 HTTPS 可确保与应用程序之间的通信保持安全。

在容器上使用 TLS/SSL 实现反向代理涉及一组与直接在主机操作系统上工作不同的过程。例如,如果您从以下位置获取证书让我们加密对于在服务器上运行的应用程序,您可以直接在主机上安装所需的软件。容器允许您采取不同的方法。使用Docker 组合,您可以为您的应用程序、Web 服务器和证书机器人客户端这将使您能够获得证书。通过执行这些步骤,您可以利用容器化工作流程的模块化和可移植性。

在本教程中,您将使用 Docker Compose 部署带有 Nginx 反向代理的 Node.js 应用程序。您将为与您的应用程序关联的域获取 TLS/SSL 证书,并确保它获得来自SSL Labs。最后,您将设置一个cron更新您的证书,以便您的域保持安全。

先决条件

要学习本教程,您将需要:

  • Ubuntu 18.04 服务器,非root用户与sudo特权和活动防火墙。有关如何设置这些的指导,请阅读此内容初始服务器设置指南.

  • Docker 和 Docker Compose 安装在您的服务器上。有关安装 Docker 的指南,请遵循步骤 1 和 2 of 如何在 Ubuntu 18.04 上安装和使用 Docker。有关安装 Compose 的指南,请遵循Step 1 of 如何在 Ubuntu 18.04 上安装 Docker Compose.

  • 已注册的域名。本教程将使用你的域名自始至终。您可以在以下位置免费获得一份Freenom,或使用您选择的域名注册商。

  • 为您的服务器设置以下两条 DNS 记录。您可以关注DigitalOcean DNS 简介有关如何将它们添加到 DigitalOcean 帐户的详细信息(如果您正在使用该帐户):

    • An A record with your_domain pointing to your server’s public IP address.
    • An A record with www.your_domain pointing to your server’s public IP address.

一切准备就绪后,您就可以开始第一步了。

步骤 1 — 克隆和测试节点应用程序

第一步,您将使用 Node 应用程序代码克隆存储库,其中包括用于使用 Compose 构建应用程序映像的 Dockerfile。然后,您将通过构建并运行应用程序来测试应用程序docker run command,无需反向代理或 SSL。

在你的非root用户的主目录,克隆nodejs-image-demo存储库来自DigitalOcean社区GitHub帐户。该存储库包含中描述的设置中的代码如何使用 Docker 构建 Node.js 应用程序.

将存储库克隆到目录中。本示例使用node_project作为目录名称。请随意根据您的喜好命名该目录:

  1. git clone https://github.com/do-community/nodejs-image-demo.git node_project

更改为node_project目录:

  1. cd节点项目

在此目录中,有一个 Dockerfile,其中包含使用以下命令构建 Node 应用程序的说明:Docker node:10 image以及当前项目目录的内容。您可以使用以下命令预览 Dockerfile 的内容:

  1. catDockerfile
Output
FROM 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" ]

这些说明通过将项目代码从当前目录复制到容器并安装依赖项来构建节点映像npm install。他们还利用 Docker缓存和图像分层通过分离副本package.json and package-lock.json,包含来自应用程序代码其余部分的副本的项目列出的依赖项。最后,指令指定容器将作为非root node对应用程序代码设置适当权限的用户以及node_modules目录。

有关此 Dockerfile 和 Node 映像最佳实践的更多信息,请浏览以下内容中的完整讨论:Step 3 of 如何使用 Docker 构建 Node.js 应用程序.

要在没有 SSL 的情况下测试应用程序,您可以使用以下命令构建并标记图像docker build-t旗帜。此示例为图像命名node-demo,但您可以随意将其命名为其他名称:

  1. docker build -t节点演示.

构建过程完成后,您可以使用以下命令列出您的图像docker images:

  1. docker images

以下输出确认应用程序映像构建:

Output
REPOSITORY TAG IMAGE ID CREATED SIZE node-demo latest 23961524051d 7 seconds ago 73MB node 10-alpine 8a752d5af4ce 3 weeks ago 70.7MB

接下来,创建容器docker run。此命令包含三个标志:

  • -p:这会发布容器上的端口并将其映射到主机上的端口。您将使用端口80在此示例中的主机上,但如果您有另一个进程在该端口上运行,请根据需要随意修改它。有关其工作原理的更多信息,请查看 Docker 文档中的讨论:端口绑定.
  • -d:这会在后台运行容器。
  • --name:这使您可以为容器指定一个容易记住的名称。

运行以下命令来构建容器:

  1. docker run --name node-demo -p 80:8080 -d node-demo

检查正在运行的容器docker ps:

  1. docker ps

以下输出确认您的应用程序容器正在运行:

Output
CONTAINER 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

You can now visit your domain to test your setup: http://your_domain. Remember to replace your_domain with your own domain name. Your application will display the following landing page:

Application Landing Page

现在您已经测试了应用程序,您可以停止容器并删除图像。使用docker ps得到你的CONTAINER ID:

  1. docker ps
Output
CONTAINER 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

停止容器docker stop。请务必更换CONTAINER ID此处列出您自己的应用程序CONTAINER ID:

  1. docker stop 4133b72391da

您现在可以删除已停止的容器和所有图像,包括未使用的和悬空的图像,docker system prune-a flag:

  1. docker系统修剪-a

Press y当输出中提示您确认是否要删除已停止的容器和映像时。请注意,这也会删除您的构建缓存。

测试应用程序映像后,您可以继续使用 Docker Compose 构建其余设置。

第 2 步 — 定义 Web 服务器配置

准备好我们的应用程序 Dockerfile 后,您将创建一个配置文件来运行 Nginx 容器。您可以从包含您的域名的最小配置开始,文档根目录、代理信息和位置块,用于将 Certbot 的请求定向到.well-known目录,它将在其中放置一个临时文件来验证您的域的 DNS 是否解析到您的服务器。

首先在当前项目目录下创建一个目录,node_project,对于配置文件:

  1. mkdirnginx-conf

创建并打开文件nano或您最喜欢的编辑器:

  1. nanonginx-conf/nginx.conf

Add the following server block to proxy user requests to your Node application container and to direct Certbot’s requests to the .well-known directory. Be sure to replace your_domain with your own domain name:

〜/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 your_domain www.your_domain;

        location / {
                proxy_pass http://nodejs:8080;
        }

        location ~ /.well-known/acme-challenge {
                allow all;
                root /var/www/html;
        }
}

该服务器块将允许您启动 Nginx 容器作为反向代理,它将请求传递到您的 Node 应用程序容器。它还允许您使用 Certbot网站根目录插件获取您的域的证书。该插件依赖于HTTP-01验证方法,它使用 HTTP 请求来证明 Certbot 可以从响应给定域名的服务器访问资源。

完成编辑后,保存并关闭文件。如果你用过nano,您可以通过按CTRL + X, then Y, and ENTER。要了解有关 Nginx 服务器和位置块算法的更多信息,请参阅这篇文章了解 Nginx 服务器和位置块选择算法.

Web 服务器配置详细信息就位后,您可以继续创建您的docker-compose.yml文件,它允许您创建应用程序服务和用于获取证书的 Certbot 容器。

第 3 步 — 创建 Docker Compose 文件

The docker-compose.yml文件将定义您的服务,包括 Node 应用程序和 Web 服务器。它将指定命名卷等详细信息,这对于在容器之间共享 SSL 凭证以及网络和端口信息至关重要。它还允许您指定创建容器时要运行的命令。该文件是定义您的服务如何协同工作的核心资源。

在当前目录中创建并打开文件:

  1. nanodocker-compose.yml

首先定义应用服务:

〜/node_project/docker-compose.yml
version: '3'

services:
  nodejs:
    build:
      context: .
      dockerfile: Dockerfile
    image: nodejs
    container_name: nodejs
    restart: unless-stopped

The nodejs服务定义包括以下内容:

  • build:这定义了配置选项,包括context and dockerfile,将在 Compose 构建应用程序映像时应用。如果您想使用注册表中的现有映像,例如码头工人中心,你可以使用image操作说明相反,包含有关您的用户名、存储库和图像标签的信息。
  • context:这定义了应用程序映像构建的构建上下文。在本例中,它是当前项目目录,用..
  • dockerfile:这指定了 Compose 将用于构建的 Dockerfile — 中查看的 DockerfileStep 1.
  • image, container_name:这些将名称应用于图像和容器。
  • restart:这定义了重新启动策略。默认为no,但在本例中,容器被设置为重新启动,除非它被停止。

请注意,您不包括此服务的绑定安装,因为您的设置侧重于部署而不是开发。有关更多信息,请阅读 Docker 文档绑定安装 and volumes.

要启用应用程序和 Web 服务器容器之间的通信,请添加一个名为的桥接网络app-network重新启动后定义:

〜/node_project/docker-compose.yml
services:
  nodejs:
...
    networks:
      - app-network

像这样的用户定义的桥接网络可以实现同一 Docker 守护进程主机上的容器之间的通信。这简化了应用程序内的流量和通信,因为它打开同一桥接网络上容器之间的所有端口,同时不向外界暴露任何端口。因此,您可以有选择地仅打开公开前端服务所需的端口。

接下来,定义webserver服务:

〜/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

此处定义的一些设置nodejs服务保持不变,但进行了以下一些更改:

  • image:这告诉 Compose 提取最新的基于阿尔卑斯山 Nginx 镜像来自 Docker 中心。欲了解更多信息alpine图片,请阅读步骤 3如何使用 Docker 构建 Node.js 应用程序.
  • ports:这会暴露端口80启用您在 Nginx 配置中定义的配置选项。

还指定了以下命名卷和绑定安装:

  • web-root:/var/www/html:这将添加您网站的静态资源,并将其复制到名为web-root,到/var/www/html容器上的目录。
  • ./nginx-conf:/etc/nginx/conf.d:这会将主机上的 Nginx 配置目录绑定挂载到容器上的相关目录,确保您对主机上的文件所做的任何更改都会反映在容器中。
  • certbot-etc:/etc/letsencrypt:这会将您的域的相关 Let’s Encrypt 证书和密钥安装到容器上的相应目录。
  • certbot-var:/var/lib/letsencrypt:这会将 Let’s Encrypt 的默认工作目录安装到容器上的相应目录。

接下来,添加配置选项certbot容器。请务必将域名和电子邮件信息替换为您自己的域名和联系电子邮件:

〜/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 sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain  -d www.your_domain 

这个定义告诉 Compose 拉取certbot/certbot 图像来自 Docker 中心。它还使用命名卷与 Nginx 容器共享资源,包括域证书和密钥certbot-etc,Let’s Encrypt 工作目录certbot-var,以及应用程序代码web-root.

再说一次,你已经使用过depends_on指定certbot一旦容器应启动webserver服务正在运行。

The commandoption 指定容器启动时要运行的命令。它包括certonly具有以下选项的子命令:

  • --webroot:这告诉 Certbot 使用 webroot 插件将文件放置在 webroot 文件夹中进行身份验证。
  • --webroot-path:指定webroot目录的路径。
  • --email:您用于注册和恢复的首选电子邮件。
  • --agree-tos:这表明您同意ACME 的订户协议.
  • --no-eff-email:这告诉 Certbot 您不希望与电子前沿基金会(电子前线)。如果您愿意,请随意忽略此内容。
  • --staging:这告诉 Certbot 您想使用 Let’s Encrypt 的临时环境来获取测试证书。使用此选项允许您测试配置选项并避免可能的域请求限制。有关这些限制的更多信息,请阅读 Let’s Encrypt 的速率限制文档.
  • -d: This allows you to specify domain names you would like to apply to your request. In this case, you’ve included your_domain and www.your_domain. Be sure to replace these with your own domains.

最后一步,添加卷和网络定义。请务必将此处的用户名替换为您自己的非root user:

〜/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

您的命名卷包括您的 Certbot 证书和工作目录卷,以及站点静态资产的卷,web-root。在大多数情况下,Docker 卷的默认驱动程序是local驱动程序,在 Linux 上它接受类似于mount command。因此,您可以使用以下命令指定驱动程序选项列表driver_opts那个安装的views主机上的目录(其中包含应用程序的静态资产)在运行时复制到卷。然后可以在容器之间共享目录内容。有关该内容的更多信息views目录,请阅读Step 2 of 如何使用 Docker 构建 Node.js 应用程序.

以下是完整的docker-compose.yml file:

〜/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 sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain  -d www.your_domain 

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  

服务定义到位后,您就可以启动容器并测试您的证书请求。

第 4 步 — 获取 SSL 证书和凭证

您可以使用以下命令启动容器docker-compose up。这将按照您指定的顺序创建并运行您的容器和服务。一旦您的域名请求成功,您的证书将被挂载到/etc/letsencrypt/live文件夹上的webserver容器。

创建服务docker-compose up-d标志,这将运行nodejs and webserver后台容器:

  1. docker 撰写 up -d

您的输出将确认您的服务已创建:

Output
Creating nodejs ... done Creating webserver ... done Creating certbot ... done

Use docker-compose ps检查您的服务状态:

  1. docker 撰写 ps

如果一切顺利的话,你的nodejs and webserver服务将是Upcertbot容器将退出并带有0状态消息:

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

如果您注意到除Up in the State列为nodejs and webserver服务,或除此之外的退出状态0为了certbot容器,请务必使用以下命令检查服务日志docker-compose logs命令。例如,如果您想检查 Certbot 日志,您可以运行:

  1. docker 撰写记录证书机器人

您现在可以检查您的凭据是否已安装到webserver容器与docker-compose exec:

  1. docker 撰写 exec网络服务器ls -la/etc/letsencrypt/live

一旦您的请求成功,您的输出将显示以下内容:

Output
total 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 your_domain

现在您知道您的请求将会成功,您可以编辑certbot服务定义以删除--staging flag.

打开docker-compose.yml file:

  1. nanodocker-compose.yml

查找文件中包含以下内容的部分certbot服务定义,并替换--staging标志在command选项与--force-renewal旗帜。这将告诉 Certbot 您想要请求与现有证书具有相同域的新证书。这certbot服务定义应具有以下定义:

〜/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 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服务,因为它已经在运行:

  1. docker 撰写up --force-recreate --no-deps certbot

以下输出表明您的证书请求已成功:

Output
Recreating certbot ... done Attaching to certbot certbot | Account registered. certbot | Renewing an existing certificate for your_domain and www.your_domain certbot | certbot | Successfully received certificate. certbot | Certificate is saved at: /etc/letsencrypt/live/your_domain/fullchain.pem certbot | Key is saved at: /etc/letsencrypt/live/your_domain phd.com/privkey.pem certbot | This certificate expires on 2022-11-03. certbot | These files will be updated when the certificate renews. certbot | NEXT STEPS: certbot | - The certificate will need to be renewed before it expires. Cert bot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setu p for instructions. certbot | Saving debug log to /var/log/letsencrypt/letsencrypt.log certbot | certbot | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - certbot | If you like Certbot, please consider supporting our work by: certbot | * Donating to ISRG / Let's Encrypt: https://letsencrypt.org/do nate certbot | * Donating to EFF: https://eff.org/donate-le certbot | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - certbot exited with code 0

证书准备就绪后,您可以继续修改 Nginx 配置以包含 SSL。

步骤 5 — 修改 Web 服务器配置和服务定义

在 Nginx 配置中启用 SSL 需要将 HTTP 重定向添加到 HTTPS 并指定 SSL 证书和密钥位置。它还将涉及指定 Diffie-Hellman 组,您将使用该组完美的前向保密.

由于您要重新创建webserver服务包含这些添加,您可以立即停止它:

  1. docker 撰写停止网络服务器

接下来,在当前项目目录中为 Diffie-Hellman 密钥创建一个目录:

  1. mkdirDH参数

使用以下命令生成您的密钥openssl command:

  1. sudo openssl dhparam -out /home/sammy/node_project/dhparam/dhparam-2048.pem 2048

生成密钥需要一些时间。

要将相关的 Diffie-Hellman 和 SSL 信息添加到您的 Nginx 配置中,请首先删除您之前创建的 Nginx 配置文件:

  1. rmnginx-conf/nginx.conf

打开该文件的另一个版本:

  1. nanonginx-conf/nginx.conf

Add the following code to the file to redirect HTTP to HTTPS and to add SSL credentials, protocols, and security headers. Remember to replace your_domain with your own domain:

〜/node_project/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 http2;
        listen [::]:443 ssl http2;
        server_name your_domain www.your_domain;

        server_tokens off;

        ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;

        ssl_buffer_size 8k;

        ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

        ssl_protocols TLSv1.2;
        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;
}

HTTP 服务器块指定 Certbot 续订请求的 Web 根目录.well-known/acme-challenge目录。它还包括一个重写指令它将对根目录的 HTTP 请求定向到 HTTPS。

HTTPS 服务器块启用ssl and http2。要详细了解 HTTP/2 如何在 HTTP 协议上进行迭代及其对网站性能的好处,请阅读以下介绍:如何在 Ubuntu 18.04 上设置支持 HTTP/2 的 Nginx。该块还包括一系列选项,以确保您使用最新的 SSL 协议和密码,并且 OSCP 装订已打开。 OSCP 装订允许您提供带有时间戳的响应证书颁发机构在最初的TLS 握手,这可以加快身份验证过程。

该块还指定您的 SSL 和 Diffie-Hellman 凭据以及密钥位置。

最后,您已将代理通行证信息移至此块,其中包括带有try_files指令,将请求指向别名的 Node.js 应用程序容器,以及该别名的位置块,其中包括安全标头,使您能够获取A对诸如以下事物的评级SSL Labs and 安全标头服务器测试站点。这些标头包括X-Frame-Options, X-Content-Type-Options, Referrer Policy, Content-Security-Policy, and X-XSS-Protection. The HTTP Strict Transport Security(HSTS) 标头已被注释掉 — 仅当您了解其含义并评估了其含义时才启用此选项“预加载”功能.

完成编辑后,保存并关闭文件。

在重新创建之前webserver服务,您需要在服务定义中添加一些内容docker-compose.yml文件,包括 HTTPS 的相关端口信息和 Diffie-Hellman 卷定义。

打开文件:

  1. nanodocker-compose.yml

In the webserver服务定义,添加以下端口映射和dhparam命名卷:

〜/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

接下来,添加dhparam音量到你的volumes定义。记得更换sammy and node_project与您的目录相匹配的目录:

〜/node_project/docker-compose.yml
...
volumes:
  ...
  webroot:
  ...
  dhparam:
    driver: local
    driver_opts:
      type: none
      device: /home/sammy/node_project/dhparam/
      o: bind

类似地web-root体积,即dhparam卷会将主机上存储的 Diffie-Hellman 密钥挂载到webserver容器。

完成编辑后保存并关闭文件。

重新创建webserver服务:

  1. docker 撰写 up -d--force-recreate --no-deps 网络服务器

检查您的服务docker-compose ps:

  1. docker 撰写 ps

以下输出表明您的nodejs and webserver服务正在运行:

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

Finally, you can visit your domain to ensure that everything is working as expected. Navigate your browser to https://your_domain, making sure to substitute your_domain with your own domain name:

Application Landing Page

浏览器的安全指示器中应出现一个锁定图标。如果您愿意,您可以导航至SSL 实验室服务器测试登陆页面 or the 安全标头服务器测试登陆页面。包含的配置选项将为您的网站赢得ASSL 实验室服务器测试的评级。为了得到一个A安全标头服务器测试的评级,您必须取消注释严格的运输安全(HSTS) 标头nginx-conf/nginx.conf file:

〜/node_project/nginx-conf/nginx.conf
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
        }

再次强调,仅当您了解其含义并评估其影响时才启用此选项“预加载”功能.

第 6 步 — 更新证书

Let’s Encrypt 证书的有效期为 90 天。您可以设置自动续订流程以确保它们不会失效。做到这一点的一种方法是创造一份工作cron调度实用程序。您可以安排一个cron使用脚本来更新您的证书并重新加载您的 Nginx 配置。

打开一个名为ssl_renew.sh在你的项目目录中:

  1. nanossl_renew.sh

将以下代码添加到脚本中以更新您的证书并重新加载您的 Web 服务器配置:

〜/node_project/ssl_renew.sh
#!/bin/bash

COMPOSE="/usr/local/bin/docker-compose --ansi never"
DOCKER="/usr/bin/docker"

cd /home/sammy/node_project/
$COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af

该脚本首先分配docker-compose二进制到一个名为的变量COMPOSE,并指定--no-ansi选项,它将运行docker-compose命令没有ANSI 控制字符。然后它会执行相同的操作docker二进制。最后,它变成了~/node_project目录并运行以下命令docker-compose命令:

  • docker-compose run:这将启动一个certbot容器并覆盖command中提供的certbot服务定义。而不是使用certonly子命令使用renew子命令,它将续订即将过期的证书。还包括--dry-run测试脚本的选项。
  • docker-compose kill:这将发送一个SIGHUP signal to the webserver容器来重新加载 Nginx 配置。

然后它运行docker system prune删除所有未使用的容器和图像。

完成编辑后关闭文件,然后使其可执行:

  1. chmod+x ssl_renew.sh

接下来,打开你的root crontab文件以指定的时间间隔运行更新脚本:

sudo crontab -e 

如果这是您第一次编辑此文件,系统会要求您选择一个编辑器:

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]: 
...

在文件末尾添加以下行:

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

这会将作业间隔设置为每五分钟一次,以便您可以测试您的续订请求是否按预期工作。您还创建了一个日志文件,cron.log,记录作业的相关输出。

五分钟后,检查cron.log确认续订请求是否成功:

  1. 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.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Killing webserver ... done
Output
… Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/your_domain/fullchain.pem (success) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Saving debug log to /var/log/letsencrypt/letsencrypt.log Killing webserver ... Killing webserver ... done Deleted Containers: 00cad94050985261e5b377de43e314b30ad0a6a724189753a9a23ec76488fd78 Total reclaimed space: 824.5kB

通过输入退出CTRL + C在您的终端中。

您现在可以修改crontab文件设置每日间隔。例如,要每天中午运行该脚本,您可以修改文件的最后一行,如下所示:

crontab
...
0 12 * * * /home/sammy/node_project/ssl_renew.sh >> /var/log/cron.log 2>&1

您还可以删除--dry-run从你的选择ssl_renew.sh script:

〜/node_project/ssl_renew.sh
#!/bin/bash

COMPOSE="/usr/local/bin/docker-compose --no-ansi"
DOCKER="/usr/bin/docker"

cd /home/sammy/node_project/
$COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af

Your cron这项工作将确保您的 Let’s Encrypt 证书不会在符合资格时续订而失效。你也可以使用 Logrotate 实用程序设置日志轮转旋转和压缩您的日志文件。

结论

您已使用容器通过 Nginx 反向代理设置和运行 Node 应用程序。您还为应用程序的域保护了 SSL 证书,并设置了cron必要时更新这些证书。

如果您有兴趣了解有关 Let’s Encrypt 插件的更多信息,请查看我们有关使用Nginx 插件 or the 独立插件.

您还可以通过以下资源了解有关 Docker Compose 的更多信息:

  • 如何在 Ubuntu 18.04 上安装 Docker Compose.
  • 如何在 Ubuntu 16.04 上使用 Docker 和 Docker Compose 配置持续集成测试环境.
  • 如何使用 Docker Compose 设置 Laravel、Nginx 和 MySQL.

The 撰写文档也是了解有关多容器应用程序的更多信息的重要资源。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Nginx、Let's Encrypt 和 Docker Compose 保护容器化 Node.js 应用程序 的相关文章

随机推荐

  • 如何在 Ubuntu 20.04 上配置静态 IP 地址

    本文介绍如何在 Ubuntu 20 04 上设置静态 IP 地址 通常 在大多数网络配置中 IP 地址由路由器 DHCP 服务器动态分配 在不同情况下可能需要设置静态 IP 地址 例如配置端口转发或运行媒体服务器 使用 DHCP 配置静态
  • 如何在 Bash 中将 stderr 重定向到 stdout

    将命令的输出重定向到文件或通过管道将其传输到另一个命令时 您可能会注意到错误消息打印在屏幕上 在 Bash 和其他 Linux shell 中 当程序执行时 它使用三个标准 I O 流 每个流都由一个数字文件描述符表示 0 stdin 标准
  • 如何在 Ubuntu 18.04 上安装 PHP

    在本教程中 我们将介绍在 Ubuntu 18 04 上安装发行版的默认 PHP 7 2 并将其与 Nginx 和 Apache 集成所需的步骤 我们还将向您展示如何安装 PHP 7 1 和 7 3 大多数流行的 PHP 框架和应用程序包括W
  • 如何在 Ubuntu 18.04 上使用 Apache 安装 Joomla

    Joomla 是最流行的开源内容管理系统之一 为数十万个网站提供支持 它是用 PHP 编写的 包含大量可以通过免费和高级扩展和主题进行扩展的功能 使用 Joomla 您可以轻松构建电子商务商店 个人网站 社交网站或博客 在本教程中 我们将解
  • 如何在 Ubuntu 20.04 上安装和使用 Wine

    Wine 是一个开源兼容层 允许您在类 Unix 操作系统 例如 Linux FreeBSD 和 macOS 上运行 Windows 应用程序 Wine是 Wine Is Not an Emulator 的缩写 它将 Windows 系统调
  • 如何在 CentOS 8 上安装 Skype

    Skype是世界上最流行的通信应用程序之一 它允许您免费拨打在线音频和视频电话 并以经济实惠的价格拨打全球手机和固定电话 本文介绍如何在 CentOS 8 上安装最新版本的 Skype 在 CentOS 上安装 Skype Skype 不是
  • 如何在 Ubuntu 20.04 上安装 Ruby

    Ruby 是当今最流行的编程语言之一 它具有优雅的语法 注重简单性和生产力 Ruby 是强大的 Ruby on Rails 框架背后的语言 在本教程中 我们将向您展示在 Ubuntu 20 04 上安装 Ruby 的三种不同方法 来自标准
  • 如何在 CentOS 7 上安装 Node.js 和 npm

    Node js 是一个跨平台的 JavaScript 运行时环境 允许服务器端执行 JavaScript 代码 Node js 主要用于后端 但作为全栈和前端解决方案也很受欢迎 npm 是 Node Package Manager 的缩写
  • 如何在 CentOS 8 上安装 Tomcat 9

    Apache Tomcat 是 Java Servlet JavaServer Pages Java 表达式语言和 Java WebSocket 技术的开源实现 它是当今世界上采用最广泛的应用程序和 Web 服务器之一 Tomcat 使用简
  • 如何在 Debian 9 上安装 Asterisk

    Asterisk 是最流行且广泛采用的用于构建通信应用程序的开源框架 它被世界各地的个人 小型企业 大型企业和政府使用 Asterisk 功能包括电话会议 语音邮件 等待音乐 呼叫转接 呼叫排队 呼叫录音 数据库存储 检索等等 在本教程中
  • 如何在 CentOS 7 上安装 Minecraft 服务器

    我的世界 是有史以来最受欢迎的游戏之一 这是一款关于放置方块并进行冒险的沙盒视频游戏 在本教程中 我们将完成在 CentOS 7 上安装和配置 Minecraft 服务器所需的步骤 我们将使用 Systemd 来运行 Minecraft 服
  • 如何在 CentOS 7 上安装 Elasticsearch

    Elasticsearch 是一个开源分布式全文搜索和分析引擎 它支持 RESTful 操作 允许您实时存储 搜索和分析大量数据 Elasticsearch 是最流行的搜索引擎之一 为具有复杂搜索要求的应用程序 例如大型电子商务商店和分析应
  • Linux 中的 Tar 命令(创建和提取档案)

    The tar命令通过将一组文件转换为存档来创建 tar 文件 它还可以提取 tar 存档 显示存档中包含的文件列表 向现有存档添加其他文件以及各种其他类型的操作 Tar 最初设计用于创建档案以将文件存储在磁带上 这就是它得名 的原因 Ta
  • 如何在 Ubuntu 18.04 上启用 SSH

    Secure Shell SSH 是一种加密网络协议 用于客户端和服务器之间的安全连接 在本教程中 我们将向您展示如何在 Ubuntu 桌面计算机上启用 SSH 启用 SSH 将允许您远程连接到 Ubuntu 计算机并安全地传输文件或执行管
  • Spring Boot @SpringBootApplication,SpringApplication 类

    春季启动 SpringBootApplication注解 春季启动 SpringBootApplication注解用于标记一个配置类 该类声明了一个或多个 Bean方法和触发器auto configuration和组件扫描 这与声明一个类相
  • 如何在 Ruby 中使用字符串

    介绍 A string是一个或多个字符的序列 可以由字母 数字或符号组成 Ruby 中的字符串是对象 与其他语言不同 字符串是mutable 这意味着可以就地更改它们 而不用创建新字符串 您几乎会在编写的每个程序中使用字符串 字符串允许您使
  • 有用的 Bash 别名和函数简介

    介绍 在命令行上操作的越多 您就越会发现您使用的大多数命令只是可用命令的很小的子集 大多数任务都是习惯性的 您可能每天都以相同的方式运行这些任务 虽然许多最常见的命令实用程序的制造商试图通过使用缩写名称来消除无关的输入 想想通过输入 ls
  • 在 Ubuntu 14.04 上使用 Consul(服务发现系统)简介

    介绍 Consul是一个分布式 高可用 数据中心感知的服务发现和配置系统 它可用于在灵活而强大的界面中呈现服务和节点 使客户端始终能够了解其所属基础设施的最新视图 Consul 提供了许多不同的功能 用于提供有关您的基础设施的一致且可用的信
  • 如何在 Ubuntu 22.04 上使用 uWSGI 和 Nginx 为 Flask 应用程序提供服务

    介绍 在本指南中 您将使用FlaskUbuntu 22 04 上的微框架 本文的大部分内容将讨论如何设置uWSGI应用服务器以及如何启动应用程序和配置Nginx充当前端反向代理 先决条件 在开始本指南之前 您应该 安装了 Ubuntu 22
  • 如何使用 Nginx、Let's Encrypt 和 Docker Compose 保护容器化 Node.js 应用程序

    介绍 有多种方法可以增强您的灵活性和安全性Node js应用 用一个反向代理 like Nginx为您提供负载平衡请求 缓存静态内容和实施传输层安全 TLS 在服务器上启用加密 HTTPS 可确保与应用程序之间的通信保持安全 在容器上使用