如何在同一VPS上共用443端口运行Docker版NPM与带Stream模块的原生Nginx?
解决方案:端口分层+流量转发
核心思路是让原生Nginx独占宿主机443端口,通过ssl_preread识别SNI信息,把普通Web流量转发给Docker内的NPM,邮件相关流量直接转发到邮件后端;同时调整NPM的端口映射,让它能正常处理SSL握手与证书自动签发。
步骤1:调整原生Nginx的Stream配置
保持原生Nginx监听宿主机443端口,修改map规则中的默认后端指向NPM的宿主机映射端口(示例用9443):
stream { map $ssl_preread_server_name $targetBackend { hostnames; default 127.0.0.1:9443; # 普通HTTPS流量转发给NPM mail.example.hu 127.0.0.1:10443; # 邮件服务后端 autoconfig.example.hu 127.0.0.1:10443; autodiscover.example.hu 127.0.0.1:10443; } server { listen 443; ssl_preread on; proxy_pass $targetBackend; # 可选:添加TCP代理优化参数 proxy_timeout 1h; proxy_connect_timeout 10s; } }
步骤2:修改NPM的Docker启动配置
将NPM容器的443端口映射到宿主机的非443端口(示例用9443),避免占用宿主机443:
- 若用
docker run命令:
docker run -d \ --name nginx-proxy-manager \ -p 80:80 \ -p 9443:443 \ # 替换原有的443:443映射 -p 81:81 \ -v ./data:/data \ -v ./letsencrypt:/etc/letsencrypt \ jc21/nginx-proxy-manager:latest
- 若用
docker-compose.yml:
services: app: image: jc21/nginx-proxy-manager:latest ports: - "80:80" - "9443:443" # 替换原有的443:443映射 - "81:81" volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt restart: unless-stopped
步骤3:验证配置有效性
- 重启原生Nginx:
systemctl restart nginx - 重启NPM容器:
docker restart nginx-proxy-manager - 测试普通Web站点:访问你的Web域名,确认HTTPS正常、证书有效(NPM会正常完成SSL握手与证书自动续签)
- 测试邮件服务:用邮件客户端连接
mail.example.hu的IMAPS/SMTPS端口,确认流量被正确路由到邮件后端
方案原理说明
- 原生Nginx的
ssl_preread仅解析SNI字段,不终止SSL连接,流量会原封不动转发给NPM,因此NPM能正常处理SSL相关逻辑 - 邮件相关的SNI流量被直接转发到指定后端,满足原生Nginx的流代理需求
- 两者不再抢占宿主机443端口,可同时稳定运行
内容的提问来源于stack exchange,提问作者answ3r
相关产品推荐
相关产品推荐

