如何使用Nginx,让我们的加密和Docker Compose来保护容器化的Node.js应用程序

按照本教程保护容器化的Node.js应用程序,该教程向您展示如何使用Docker Compose使用Nginx反向代理部署Node.js应用程序。您将使用Let's Encrypt获取应用程序域的证书,并确保您的应用程序获得高安全评级。

介绍

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

在容器上使用TLS / SSL实现反向代理涉及一组不同的过程,而不是直接在主机操作系统上工作。 例如,如果您从服务器上运行的应用程序获取Let's Encrypt的证书,则可以直接在主机上安装所需的软件。 容器允许您采取不同的方法。 使用Docker Compose ,您可以为应用程序,Web服务器和Certbot客户端创建容器,以便您获取证书。 通过执行这些步骤,您可以利用容器化工作流程的模块化和便携性。

在本教程中,您将使用Docker Compose部署带有Nginx反向代理的Node.js应用程序。 您将获得与您的应用程序关联的域的TLS / SSL证书,并确保它从SSL实验室获得高安全性评级。 最后,您将设置一个cron作业来续订证书,以便您的域保持安全。

先决条件

要学习本教程,您需要:

  • Ubuntu 18.04服务器,具有sudo权限的非root用户和活动防火墙。 有关如何设置这些内容的指导,请参阅此初始服务器设置指南
  • Docker和Docker Compose安装在您的服务器上。 有关安装Docker的指导,请按照如何在Ubuntu 18.04上安装和使用Docker的第1步和2进行操作。 有关安装Compose的指导,请按照如何在Ubuntu 18.04上安装Docker Compose的第1步进行操作。
  • 注册域名。 本教程将始终使用example.com 您可以在Freenom免费获得一个,或使用您选择的域名注册商。
  • 为您的服务器设置了以下两个DNS记录。 您可以按照DigitalOcean DNS的这一介绍 ,了解如何将它们添加到DigitalOcean帐户的详细信息,如果您正在使用它:

    • 带有example.com的A记录,指向服务器的公共IP地址。
    • 带有www. example.com的A记录www. example.com www. example.com指向您服务器的公共IP地址。

第1步 - 克隆和测试节点应用程序

作为第一步,我们将使用Node应用程序代码克隆存储库,其中包括我们将使用Compose构建应用程序映像的Dockerfile。 我们可以首先使用docker run命令构建和运行应用程序来测试应用程序,而无需使用反向代理或SSL。

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

将存储node_project到名为node_project的目录中:

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

切换到node_project目录:

cd  node_project

在此目录中,有一个Dockerfile,其中包含使用Docker node:10构建Node应用程序的说明node:10 image和当前项目目录的内容。 您可以通过键入以下内容来查看Dockerfile的内容:

cat Dockerfile
FROM node:10

RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app

WORKDIR /home/node/app

COPY package*.json ./

RUN npm install

COPY . .

COPY --chown=node:node . .

USER node

EXPOSE 8080

CMD [ "node", "app.js" ]

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

有关此Dockerfile和节点映像最佳实践的更多信息,请参阅如何使用Docker构建Node.js应用程序的第3步中的完整讨论。

要在没有SSL的情况下测试应用程序,可以使用docker build-t标志构建和标记映像。 我们将调用图像node-demo ,但您可以将其命名为:

docker build -t node-demo .

构建过程完成后,您可以使用docker images列出docker images

docker images

您将看到以下输出,确认应用程序映像构建:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
node-demo           latest              23961524051d        7 seconds ago       896MB
node                10                  8a752d5af4ce        10 days ago         894MB

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

  • -p :这将在容器上发布端口并将其映射到主机上的端口。 我们将在主机上使用端口80 ,但如果您在该端口上运行另一个进程,则可以根据需要随意修改它。 有关其工作原理的更多信息,请参阅有关端口绑定的Docker文档中的此讨论。
  • -d :这在后台运行容器。
  • --name :这允许我们给容器一个令人难忘的名字。

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

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

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

docker ps

您将看到确认您的应用程序容器正在运行的输出:

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

您现在可以访问您的域来测试您的设置: http:// example.com 请记住将example.com替换为您自己的域名。 您的应用程序将显示以下登录页面:

申请登陆页面

现在您已经测试了应用程序,您可以停止容器并删除图像。 再次使用docker ps获取您的CONTAINER ID

docker ps
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

docker stop 4133b72391da

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

docker system prune -a

在输出中提示时键入y以确认您要删除已停止的容器和图像。 请注意,这也将删除您的构建缓存。

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

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

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

首先,在配置文件的当前项目目录中创建一个目录:

mkdir nginx-conf

使用nano或您喜欢的编辑器打开文件:

nano nginx-conf/nginx.conf

添加以下服务器块以将代理用户请求添加到节点应用程序容器,并将Certbot的请求定向到.well .well-known目录。 请务必使用您自己的域名替换example.com

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

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

完成编辑后,保存并关闭文件。 要了解有关Nginx服务器和位置块算法的更多信息,请参阅有关了解Nginx服务器和位置块选择算法的文章

有了Web服务器配置详细信息,我们可以继续创建docker-compose.yml文件,这将允许我们创建应用程序服务和我们将用于获取证书的Certbot容器。

第3步 - 创建Docker Compose文件

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

打开当前目录中的文件:

nano docker-compose.yml

首先,定义应用程序服务:

〜/ node_project /搬运工-compose.yml
version: '3'

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

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

  • build :这定义了Compose构建应用程序映像时将应用的配置选项,包括contextdockerfile 如果您想使用Docker Hub等注册表中的现有映像,则可以使用image指令 ,并提供有关用户名,存储库和图像标记的信息。
  • context :这定义了应用程序映像构建的构建上下文。 在这种情况下,它是当前的项目目录。
  • dockerfile :这指定Compose将用于构建的Dockerfile - 您在第1步中查看的Dockerfile。
  • imagecontainer_name :这些名称适用于图像和容器。
  • restart :这定义了重启策略。 默认值为no ,但我们已将容器设置为重新启动,除非它已停止。

请注意,我们不包括使用此服务的绑定装入,因为我们的设置侧重于部署而不是开发。 有关更多信息,请参阅有关绑定装入的Docker文档。

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

〜/ node_project /搬运工-compose.yml
services:
  nodejs:
...
    networks:
      - app-network

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

接下来,定义webserver服务:

〜/ node_project /搬运工-compose.yml
...
 webserver:
    image: nginx:latest
    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从Docker Hub中提取最新的Nginx图像
  • 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的加密证书和密钥挂载到容器上的相应目录。
  • certbot-var:/var/lib/letsencrypt :这将Let的Encrypt的默认工作目录挂载到容器上的相应目录。

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

〜/ node_project /搬运工-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@example.com --agree-tos --no-eff-email --staging -d example.com  -d www.example.com 

此定义告诉Compose从Docker Hub中提取certbot / certbot映像 它还使用命名卷与Nginx容器共享资源,包括域证书和certbot-etc密钥, certbot-var的Let's Encrypt工作目录以及web-root的应用程序代码。

同样,我们使用depends_on指定一旦webserver服务运行,就应该启动certbot容器。

我们还包含一个command选项,指定在启动容器时要运行的命令。 它包括certonly子命令,其中包含以下选项:

  • --webroot :这告诉Certbot使用webroot插件将文件放在webroot文件夹中进行身份验证。
  • --webroot-path :指定webroot目录的路径。
  • --email :您首选的电子邮件,用于注册和恢复。
  • --agree-tos :这表明您同意ACME的订户协议
  • --no-eff-email :这告诉Certbot您不希望与电子前沿基金会 (EFF)分享您的电子邮件。 如果您愿意,请随意省略。
  • --staging :这告诉Certbot你想使用Let's Encrypt的登台环境来获取测试证书。 使用此选项可以测试配置选项并避免可能的域请求限制。 有关这些限制的更多信息,请参阅Let's Encrypt的速率限制文档
  • -d :这允许您指定要应用于请求的域名。 在这种情况下,我们已经包含了example.comwww. example.com www. example.com 请务必使用您自己的域首选项替换它们。

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

〜/ node_project /搬运工-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命令的选项。 由于这个原因,我们可以使用driver_opts指定驱动程序选项列表,该列表将主机上的views目录(包含应用程序的静态资源)挂载到运行时的卷。 然后可以在容器之间共享目录内容。 有关views目录内容的更多信息,请参阅如何使用Docker构建Node.js应用程序的第2步

完成后, docker-compose.yml文件将如下所示:

〜/ node_project /搬运工-compose.yml
version: '3'

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

  webserver:
    image: nginx:latest
    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@example.com --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  

有了服务定义,您就可以启动容器并测试证书请求了。

第4步 - 获取SSL证书和凭据

我们可以使用docker-compose up启动我们的容器,它将按照我们指定的顺序创建和运行我们的容器和服务。 如果我们的域请求成功,我们将在输出中看到正确的退出状态,并在webserver容器的/etc/letsencrypt/live文件夹中安装正确的证书。

使用docker-compose up-d标志创建服务,该标志将在后台运行nodejswebserver容器:

docker-compose up -d

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

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

使用docker-compose ps ,检查服务的状态:

docker-compose ps

如果一切都成功,您的nodejswebserver服务应该是Up ,并且certbot容器将退出并显示0状态消息:

  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

如果您在nodejswebserver服务的State列中看到除Up之外的任何内容,或者certbot容器的除0以外的退出状态,请务必使用certbot docker-compose logs命令检查服务日志:

docker-compose logs service_name

您现在可以使用docker-compose exec检查您的凭据是否已挂载到webserver容器:

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

如果您的请求成功,您将看到如下输出:

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 example.com

既然您知道您的请求将成功,您可以编辑certbot服务定义以删除--staging标志。

打开docker-compose.yml

nano docker-compose.yml

使用certbot服务定义查找文件部分,并使用--force-renewal标志替换command选项中的--staging标志,该标志将告知Certbot您要请求具有相同域的新证书。现有证书。 certbot服务定义现在应如下所示:

〜/ node_project /搬运工-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@example.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com
...

您现在可以运行certbot docker-compose up来重新创建certbot容器及其相关卷。 我们还将包含--no-deps选项,告诉Compose它可以跳过启动webserver服务,因为它已经在运行:

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

您将看到表明您的证书申请成功的输出:

certbot      | 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

有了您的证书,您可以继续修改您的Nginx配置以包含SSL。

第5步 - 修改Web服务器配置和服务定义

在我们的Nginx配置中启用SSL将涉及向HTTPS添加HTTP重定向并指定我们的SSL证书和密钥位置。 它还将涉及指定我们将用于Perfect Forward Secrecy的 Diffie-Hellman组。

由于您要重新创建webserver以包含这些添加项,因此您现在可以停止它:

docker-compose stop webserver

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

mkdir dhparam

使用openssl命令生成密钥:

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

生成密钥需要一些时间。

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

rm nginx-conf/nginx.conf

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

nano nginx-conf/nginx.conf

将以下代码添加到文件中以将HTTP重定向到HTTPS并添加SSL凭据,协议和安全标头。 请记住将example.com替换为您自己的域名:

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

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

HTTPS服务器块启用sslhttp2 要了解有关HTTP协议的HTTP / 2迭代方式及其对网站性能的好处的更多信息,请参阅如何在Ubuntu 18.04上使用HTTP / 2支持设置Nginx的简介。 此块还包括一系列选项,以确保您使用最新的SSL协议和密码,并打开OSCPStapling。 OSCPStapling允许您在初始TLS握手期间从证书颁发机构提供带时间戳的响应,这可以加快身份验证过程。

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

最后,我们将代理传递信息移动到此块,包括带有try_files指令的位置块,将请求指向我们的别名Node.js应用程序容器,以及该别名的位置块,其中包含将使我们能够使用的安全头获得诸如SSL实验室安全标头服务器测试站点之类的评级。 这些标头包括X-Frame-OptionsX-Content-Type-OptionsReferrer PolicyContent-Security-PolicyX-XSS-Protection HTTP Strict Transport Security (HSTS)标头已注释掉 - 只有在您了解其含义并评估其“预加载”功能时才启用此功能

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

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

打开文件:

nano docker-compose.yml

webserver服务定义中,添加以下端口映射和名为volume的dhparam

〜/ node_project /搬运工-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定义中:

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

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

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

重新创建webserver

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

使用docker-compose ps检查您的服务:

docker-compose ps

您应该看到指示您的nodejswebserver服务正在运行的输出:

  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

最后,您可以访问您的域,以确保一切正常运行。 将浏览器导航到https:// example.com ,确保用您自己的域名替换example.com 您将看到以下登录页面:

申请登陆页面

您还应该在浏览器的安全指示器中看到锁定图标。 如果您愿意,可以导航到SSL Labs Server Test登录页面Security Headers服务器测试登录页面 我们已包含的配置选项应使您的网站获得A评级。

第6步 - 续订证书

我们的加密证书有效期为90天,因此您需要设置自动续订流程以确保它们不会失效。 一种方法是使用cron调度实用程序创建作业。 在这种情况下,我们将使用一个脚本来安排一个cron作业,该脚本将更新我们的证书并重新加载我们的Nginx配置。

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

nano ssl_renew.sh

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

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

除了指定docker-compose.yml docker-compose二进制文件的位置外,我们还指定了docker-compose.yml文件的位置,以便运行docker-compose.yml docker-compose命令。 在这种情况下,我们使用certbot docker-compose run来启动一个certbot容器,并用另一个command覆盖我们的服务定义中提供的commandrenew子命令,它将更新接近过期的证书。 我们在这里包含了--dry-run选项来测试我们的脚本。

然后,脚本使用docker-compose killSIGHUP信号发送到webserver容器以重新加载Nginx配置。 有关使用此过程重新加载Nginx配置的更多信息,请参阅Docker博客文章,了解如何使用Docker部署官方Nginx映像

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

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以查看续订请求是否成功:

tail -f /var/log/cron.log

您应该看到确认成功续订的输出:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** 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

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

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

您还需要从ssl_renew.sh脚本中删除--dry-run选项:

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

您的cron作业将确保您的Let's Encrypt证书在符合条件时通过续订而不会失效。

结论

您已使用容器来设置和运行具有Nginx反向代理的Node应用程序。 您还为应用程序的域保护了SSL证书,并设置了一个cron作业,以便在必要时续订这些证书。

如果您有兴趣了解有关Let's Encrypt插件的更多信息,请参阅我们关于使用Nginx插件独立插件的文章

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

Compose文档也是了解有关多容器应用程序的更多信息的绝佳资源。


分享按钮