使用 Docker 设置具有自动 SSL 生成的 Nginx 反向代理

什么是反向代理? 它的优点是什么?

什么是反向代理? 反向代理是一种位于许多其他服务器前面的服务器,并将客户端请求转发到适当的服务器。 来自服务器的响应也被代理服务器接收并转发给客户端。

为什么要使用这样的设置? 有几个很好的理由。 此设置可用于设置负载平衡器、缓存或防止攻击。

我不在这里详细介绍。 相反,我将向您展示如何利用反向代理的概念在同一台服务器上设置多个服务。

拍摄与您在上面看到的相同的图像。 您可以做的是在 docker 容器中以反向代理模式运行 Ngnix 服务器。 其他 Web 服务也可以在各自的容器中运行。

Nginx 容器将被配置为知道哪个 Web 服务在哪个容器中运行。

这是节省在不同服务器中托管每个服务的成本的好方法。 借助反向代理服务器,您可以在同一 Linux 服务器上运行多个服务。

使用 Docker 将 Nginx 设置为反向代理以在同一服务器上部署多个服务

让我向您展示如何配置上述设置。

通过这些步骤,您可以安装多个在 Nginx 下运行的基于 Web 的应用程序容器,每个独立容器对应于其各自的域或子域。

首先,让我们看看您需要什么来学习本教程。

先决条件

您将需要以下知识才能轻松开始本教程。 无论如何,没有它们你也可以过得去。

  • Linux 系统/服务器。 您可以在几分钟内轻松部署 Linux 服务器 Linode云服务.
  • 熟悉Linux命令和终端。
  • Docker的基础知识。
  • 你应该在你的 Linux 服务器上安装了 Docker 和 Docker Compose。 请阅读我们在 CentOS 上安装 Docker 和 Docker Compose 的指南。
  • 您还应该拥有一个域(以便您可以在子域上设置服务)。

我使用 domain.com 作为 example 教程中的域名。 请确保根据您自己的域或子域进行更改。

除上述以外,还请确认以下事项:

更改域的 DNS 记录

在您的域名提供商的 A/AAAA 或 CNAME 记录面板中,确保域和子域(包括 www)都指向您服务器的 IP 地址。

这是个 example 供你参考:

主机名IP地址TTL
域名.com172.105.50.178默认
*172.105.50.178默认
sub0.domain.com172.105.50.178默认
sub1.domain.com172.105.50.178默认

交换空间

为确保您的所有容器应用程序在部署后都不会出现内存不足的情况,您的系统上必须有必要的交换空间。

您始终可以根据系统上的可用 RAM 调整交换。 您可以根据单个服务器上的应用程序容器包并估计它们的累积 RAM 使用量来决定交换空间。

第一步:设置 Nginx 反向代理容器

从设置您的 nginx 反向代理开始。 创建一个名为“reverse-proxy”的目录并切换到它:

mkdir reverse-proxy && cd reverse-proxy

创建一个名为 docker-compose.yml,在你最喜欢的基于终端的文本编辑器中打开它,比如 Vim 或 纳米.

对于 nginx 反向代理,我将使用 jwilder/nginx-代理 图片。 将以下内容复制并粘贴到 docker-compose.yml 文件中:

version: "3.7"

services:

    reverse-proxy:
        image: "jwilder/nginx-proxy:latest"
        container_name: "reverse-proxy"
        volumes:
            - "html:/usr/share/nginx/html"
            - "dhparam:/etc/nginx/dhparam"
            - "vhost:/etc/nginx/vhost.d"
            - "certs:/etc/nginx/certs"
            - "/run/docker.sock:/tmp/docker.sock:ro"
        restart: "always"
        networks: 
            - "net"
        ports:
            - "80:80"
            - "443:443"

现在让我们来看看 compose 文件的重要部分:

  • 您已经声明了四个卷,html、dhparam、vhost 和 certs。 它们是持久性数据,即使在容器关闭后您也绝对希望保留这些数据。 这 html & vhost 卷将在接下来非常重要 让我们加密 容器部署。 它们旨在协同工作。
  • docker socker 以只读方式安装在容器内。 这是反向代理容器生成 nginx 的配置文件、检测具有特定环境变量的其他容器所必需的。
  • Docker 重启策略设置为 always. 其他选项包括 on-failureunless-stopped. 在这种情况下,似乎总是更合适。
  • 端口 80 和 443 分别绑定到主机用于 http 和 https。
  • 最后,它使用不同的网络,而不是默认的桥接网络。

使用用户定义的网络非常重要。 这将有助于隔离所有要代理的容器,同时使反向代理容器能够将客户端转发到他们想要/预期的容器,并让容器相互通信(这对于默认桥接网络是不可能的除非 icc 设定为 true 对于守护进程)。

请记住,YML 对制表符和缩进非常挑剔。

第 2 步:设置用于自动生成 SSL 证书的容器

为此,您可以使用 jrcs/letsencrypt-nginx-proxy-companion 容器图像。

一样的 docker-compose.yml 之前使用的文件,添加以下行:

    letsencrypt:
        image: "jrcs/letsencrypt-nginx-proxy-companion:latest"
        container_name: "letsencrypt-helper"
        volumes:
            - "html:/usr/share/nginx/html"
            - "dhparam:/etc/nginx/dhparam"
            - "vhost:/etc/nginx/vhost.d"
            - "certs:/etc/nginx/certs"
            - "/run/docker.sock:/var/run/docker.sock:ro"
        environment:
            NGINX_PROXY_CONTAINER: "reverse-proxy"
            DEFAULT_EMAIL: "[email protected]"
        restart: "always"
        depends_on:
            - "reverse-proxy"
        networks: 
            - "net"

在此服务定义中:

  • 您使用的卷与用于反向代理容器的卷完全相同。 这 htmlvhost 卷共享是必要的 Letsencrypt 的 ACME 挑战 要成功。 这个容器将在里面生成证书 /etc/nginx/certs, 在容器中。 这就是您与反向代理容器共享此卷的原因。 这 dhparam 卷将包含 dhparam 文件。 安装套接字以检测具有特定环境变量的其他容器。
  • 在这里,您定义了两个环境变量。 这 NGINX_PROXY_CONTAINER 变量指向反向代理容器。 将其设置为容器的名称。 这 DEFAULT_EMAIL 是为每个域/子域生成证书时将使用的电子邮件。
  • depends_on 设置了选项,以便此服务首先等待反向代理启动,然后只有这样,它才会启动。
  • 最后,这个容器也共享同一个网络。 这是两个容器进行通信所必需的。

第 3 步:完成 docker compose 文件

完成服务定义后,使用以下行完成 docker-compose 文件:

volumes:
  certs:
  html:
  vhost:
  dhparam:

networks:
  net:
    external: true

网络 net 设置为外部,因为代理容器也必须使用此网络。 如果我们离开网络由 docker-comspose,网络名称将取决于当前目录。 这将创建一个名称奇怪的网络。

除此之外,其他容器无论如何都必须将该网络设置为外部网络,否则这些撰写文件也必须驻留在同一目录中,这都不理想。

因此,使用创建网络

 docker network create net

以下是本次活动的全部内容 docker-compose.yml 文件。

version: "3.7"

services:

    reverse-proxy:
        image: "jwilder/nginx-proxy:latest"
        container_name: "reverse-proxy"
        volumes:
            - "html:/usr/share/nginx/html"
            - "dhparam:/etc/nginx/dhparam"
            - "vhost:/etc/nginx/vhost.d"
            - "certs:/etc/nginx/certs"
            - "/run/docker.sock:/tmp/docker.sock:ro"
        restart: "always"
        networks: 
            - "net"
        ports:
            - "80:80"
            - "443:443"
    letsencrypt:
        image: "jrcs/letsencrypt-nginx-proxy-companion:latest"
        container_name: "letsencrypt-helper"
        volumes:
            - "html:/usr/share/nginx/html"
            - "dhparam:/etc/nginx/dhparam"
            - "vhost:/etc/nginx/vhost.d"
            - "certs:/etc/nginx/certs"
            - "/run/docker.sock:/var/run/docker.sock:ro"
        environment:
            NGINX_PROXY_CONTAINER: "reverse-proxy"
            DEFAULT_EMAIL: "[email protected]"
        restart: "always"
        depends_on:
            - "reverse-proxy"
        networks: 
            - "net"
volumes:
  certs:
  html:
  vhost:
  dhparam:

networks:
  net:
    external: true

最后,您可以使用以下命令部署这两个容器(Ngnix 和 Let’s Encrypt):

docker-compose up -d

第 4 步:验证 Ngnix 反向代理是否正常工作

服务于前端的容器需要定义两个环境变量。

VIRTUAL_HOST:用于生成反向代理配置

LETSENCRYPT_HOST:用于生成必要的证书

确保这两个变量的值正确。 您可以像这样使用反向代理运行 nginx-dummy 映像:

docker run --rm --name nginx-dummy -e VIRTUAL_HOST=sub.domain.com -e LETSENCRYPT_HOST=sub.domain.com -e VIRTUAL_PORT=80 --network net -d nginx:latest

现在,如果您转到上一个命令中使用的子域,您应该会看到来自 Ngnix 服务器的消息。

Ngnix 反向代理

成功测试后,您可以停止正在运行的 docker 容器:

docker stop nginx-dummy

如果您不打算使用 Ngnix 反向代理,也可以停止它:

docker-compose down

步骤 5:使用反向代理运行其他服务容器

设置其他容器以便它们可以被代理的过程非常简单。

我将用两个实例来展示它 下一云 一会儿部署。 让我先告诉你你在这里做什么。

不要绑定到任何端口

容器可以省略服务于前端的端口。 反向代理容器会自动检测到这一点。

(可选)定义 VIRTUAL_PORT

如果反向代理容器检测不到端口,可以定义另一个环境变量,命名为 VIRTUAL_PORT 使用为前端提供服务的端口或您想要代理的任何服务,例如“80”或“7765”。

设置让我们加密特定于容器的电子邮件

您可以覆盖 DEFAULT_EMAIL 变量并通过将电子邮件 ID 设置为环境变量,为特定容器/Web 服务的域/子域证书设置特定的电子邮件地址 LETSENCRYPT_EMAIL. 这适用于每个容器。

现在您已经了解了所有这些内容,让我向您展示部署 Nextcloud 实例的命令,该实例将使用 nginx 代理容器进行代理,并将启用 TLS(SSL/HTTPS)。

这不是一个理想的部署。 以下命令仅用于演示目的。

docker run --name nextcloud --network net -e VIRTUAL_HOST="sub0.domain.com" -e LETSENCRYPT_HOST="sub0.domain.com" -d nextcloud:19.0.2

在里面 example,您使用与反向代理容器相同的网络,使用适当的子域定义了两个环境变量(相应地设置您的)。 几分钟后,您应该会看到 Nextcloud 在 sub0.domain.com 上运行。 在浏览器中打开它进行验证。

您可以像这样在不同的子域上部署另一个 Nextcloud 实例,如下所示:

docker run --name anothernextcloud --network net -e VIRTUAL_HOST="sub1.domain.com" -e LETSENCRYPT_HOST="sub1.domain.com" -d nextcloud:19.0.2

现在您应该看到在同一服务器上的不同子域上运行的不同 Nextcloud 实例。

使用这种方法,您可以在不同子域下服务的同一台服务器上部署不同的 Web 应用程序,这非常方便。

跟着

现在您已经完成了此设置,您可以继续在实际部署中使用以下示例:

  • 使用 Docker 安装 Matrix Synapse Homeserver
  • 在同一台服务器上安装多个 Discourse Container

如需更多此类文章,请订阅我们的时事通讯,或考虑成为会员。 如有任何疑问,请随时在下面发表评论。