编辑:@pfaffman 将 @tophee 之前撰写的内容重写为一个独立主题。我尚未对此进行测试,并且调整了 Chris 的措辞,因此任何错误很可能归因于 @pfaffman。
是否有理由不使用 NGINX Proxy Manager,而是按照 Run other websites on the same machine as Discourse 中的描述手动操作?
我已经在使用了。我在家庭服务器上运行它已经有一段时间了。当我将 Discourse 实例迁移到新的云服务器时,我意识到自己已经忘记了四年前在旧服务器上设置的 NGINX 反向代理的大部分细节,于是我想:为什么不使用 NGINX Proxy Manager 呢?令我惊讶的是,我发现它在 Meta 论坛上被提及的次数非常少,因此我开始怀疑是否有什么缺点是我可能遗漏的……
确实,这需要一些试错,但我按以下方式使其正常工作(不保证这是最佳方法——事实上,我知道肯定有更好的方法——所以非常欢迎纠正和改进):
首先,访问您的 Discourse 实例有两种方式:1. 通过暴露端口,2. 通过 WebSocket。我相信我在这个论坛的某个地方了解到 WebSocket 更快/更高效,所以我使用的是 WebSocket,但暴露端口应该容易得多,所以如果您无法让 WebSocket 正常工作,请尝试暴露端口。因此,为了避免混淆:要通过端口访问 Discourse,请遵循下面的步骤 0、1、2、3、4 和 8。如果您想使用 WebSocket,请遵循步骤 0、1、5、6、7、8 和 9。
0. 起点
因此,假设您已经完成了 30 分钟标准安装,并且假设您尚未让 Discourse 获取 Let’s Encrypt 证书——因为在使用反向代理时不需要它。NGINX Proxy Manager 会处理此事。不过,如果您已经有了证书也没关系。NGINX Proxy Manager 会简单地获取一个新证书。
1. 安装 NGINX Proxy Manager
下一步是安装 NGINX Proxy Manager,这样您就会多运行两个 Docker 容器(NGINX Proxy Manager 及其数据库容器)。
接下来是您询问的棘手部分。
第一个障碍是 Discourse 运行在默认的 Docker bridge 网络上,而 NGINX Proxy Manager 默认运行在默认的“用户创建网络”上(在我的情况下称为 npm_default),这意味着 NGINX Proxy Manager 无法看到 Discourse。![]()
2. 将所有容器移至默认 bridge 网络
因此,只要 我不知道 Discourse 是否可以移动到自定义网络以及如何进行,我们就必须将 NGINX Proxy Manager 移动到默认的 bridge 网络。我们可以通过在 Docker Compose 文件 中的两个 NGINX Proxy Manager 容器添加 network_mode: bridge 来实现这一点。
3. 使用 IP 地址而不是服务名称
接下来的问题是,如果您只是将其移动到 bridge 网络,标准的 Docker Compose 文件将不再起作用。NGINX Proxy Manager 将无法再找到其数据库容器。这是因为服务名称的内部 DNS 解析(Docker Compose 文件依赖于此)仅在用户创建的网络上可用,而在默认 Docker 网络上不可用。因此,我们不得不使用硬编码的 IP 地址(这就是为什么这绝对不是最佳解决方案,因为如果您的容器 IP 发生变化,它将失效)。所以您需要启动容器,即使您知道它无法工作,记下 NGINX Proxy Manager 数据库容器的 IP,并将 Docker Compose 文件中的 DB_MYSQL_HOST: "db" 替换为 DB_MYSQL_HOST: "<db_container_IP>"。
现在所有容器都应该在默认的 bridge 网络上,以便 NGINX Proxy Manager 能够看到 Discourse 及其数据库。
4. 使 Discourse 可访问
但是,“看到”Discourse 和能够访问它并不是一回事。因此,您需要确保 Discourse 会接受 NGINX Proxy Manager 转发给它的任何流量。如果您不在乎使用 WebSocket,我想您可以直接将 NGINX Proxy Manager 指向 Discourse 容器 IP 的 80 端口(而不是 443 端口),如下所示:
不过我还没有测试过这一点。正如我所提到的,我使用的是 WebSocket 设置,这需要一些额外的步骤。请注意,当您使用 WebSocket 时,上述主机名/IP 和端口将被忽略。
5. 配置 app.yml 以使用 WebSocket
这已在 原始帖子 中解释,因此我不再赘述。
6. 在 NGINX Proxy Manager 容器中挂载 WebSocket
我们需要通过将其挂载为卷来让 NGINX Proxy Manager 访问 WebSocket:- /var/discourse/shared/standalone/nginx.http.sock:/var/discourse/shared/standalone/nginx.http.sock。这是对默认 NGINX Proxy Manager Docker Compose 文件的最终更改,因此以下是对我有效的最终版本:
version: '3'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
network_mode: bridge
ports:
- '80:80'
- '81:81'
- '443:443'
environment:
DB_MYSQL_HOST: "172.17.0.6"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "my-super-safe-pwd"
DB_MYSQL_NAME: "npm"
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
- /var/discourse/shared/standalone/nginx.http.sock:/var/discourse/shared/standalone/nginx.http.sock
db:
image: 'jc21/mariadb-aria:latest'
restart: unless-stopped
network_mode: bridge
environment:
MYSQL_ROOT_PASSWORD: 'my-super-safe-pwd'
MYSQL_DATABASE: 'npm'
MYSQL_USER: 'npm'
MYSQL_PASSWORD: 'my-super-safe-pwd'
volumes:
- ./data/mysql:/var/lib/mysql
7. 配置 NGINX Proxy Manager 以使用 WebSocket
最后一步:告诉 NGINX Proxy Manager 使用 WebSocket。据我回忆,仅开启“WebSocket 支持”是不够的,因此我将 原始帖子中的 NGINX 位置 复制到了“高级”选项卡中,如下所示:
我在“自定义位置”选项卡下无法使其工作。
8. 不要忘记激活 SSL
我没有在 NGINX Proxy Manager 中提及 SSL 配置,因为它看起来非常显而易见,而且我认为在过程中的哪个点激活它并不重要。所以如果您还没有这样做,我的配置如下所示:
9. 注意事项
tl;dr 每当您重启 Discourse 容器时,您也需要重启主 NGINX Proxy Manager 容器(无需重启数据库)。
如果您通过 WebSocket 访问 Discourse,需要注意,当您重建 Discourse 容器时(为了更新基础镜像,每几个月就需要这样做一次),之前的 WebSocket 将被删除并创建一个新的。因此,NGINX Proxy Manager 将失去与 Discourse 实例的联系并抛出 502 错误。也许未来的 NGINX Proxy Manager 更新能够自动找到新的 WebSocket,但目前(2022 年 1 月),除非您重启 NGINX Proxy Manager,否则它无法找到您重建的 Discourse 容器。
解释
如果您想知道为什么上述说明将 WebSocket 与端口结合起来,简单的原因是我在撰写此帖子时突然想到,当我们使用 WebSocket 时,NGINX Proxy Manager 和 Discourse 甚至可能不需要在同一个 Docker 网络上。当这一点得到确认后,没有人觉得有必要完全重写说明。
这是支持论坛最迷人的方面之一:很好地描述您的问题往往会引导您找到解决方案,甚至无需发布您的问题。在这种情况下,我正在回答别人的问题,但也可能找到了自己问题的答案。![]()



