105
0
1

一台服务器部署多个服务:Dockge + Nginx Proxy Manager + 3X-UI 端口复用与 HTTPS 教程

文章摘要
|
SELF-HOSTING · DOCKER · REVERSE PROXY
一台服务器部署多个服务:Dockge + Nginx Proxy Manager + MyIP + IT-Tools + 3X-UI

最终效果:一台 VPS 上同时运行多个 Web 服务,只有 Nginx Proxy Manager 占用公网 80/443;其他服务使用独立内部端口,再通过不同子域名访问。本文从零开始,部署完成后逐项验证 HTTPS、反向代理、容器状态和管理面板。

Ubuntu / DebianDocker ComposeDockge :5001NPM :80/:81/:443MyIP :18966IT-Tools :80883X-UI :2053 示例

先确定最终架构,不要边装边改端口

目标先固定“谁占公网端口、谁走内部端口”,后面所有 Compose 和反向代理都按这张表执行。
浏览器多个子域名
80 / 443NPM 唯一公网入口
内部服务5001 / 18966 / 8088 / 2053
Docker / Host实际应用
子域名示例服务后端端口是否直接公网开放
dockge.example.comDockge5001不建议
npm.example.comNPM Admin81限制来源
ip.example.comMyIP18966
tools.example.comIT-Tools8088
panel.example.com3X-UI2053 示例
完成标准你已经决定:只有 NPM 对公网提供 80/443;其它服务后面全部从 NPM 进入。

检查服务器、Docker 与端口占用

目标确认 Docker 可用,而且 80/81/443/5001/18966/8088 没有和现有服务冲突。

建议使用 Ubuntu 22.04/24.04 或 Debian 11/12。Docker 和 Compose V2 应已经安装。

bash · 基础检查
docker --version
docker compose version

sudo ss -lntp | grep -E ':(80|81|443|5001|18966|8088|2053)\b' || true
预期结果Docker 与 Compose 能输出版本;准备使用的端口没有被其它反向代理或容器占用。
常见错误:80/443 已被占用如果服务器已经运行 KPanel、宝塔、Caddy 或宿主机 Nginx,就不要再让 NPM绑定同样端口。必须先决定谁是最终公网入口。

为每个服务准备 DNS 记录

目标让所有子域名都解析到同一台 VPS,后续 NPM 只根据 Host 域名分流。
类型名称目标
Adockge你的 VPS IPv4
Aip你的 VPS IPv4
Atools你的 VPS IPv4
Apanel你的 VPS IPv4
bash · DNS 验证
dig +short dockge.example.com
dig +short ip.example.com
dig +short tools.example.com
dig +short panel.example.com
完成标准四个域名都返回你的服务器公网 IP。

部署 Dockge:以后用它管理 Compose 栈

目标部署 Dockge,并固定 stacks 目录为 /opt/stacks

Dockge 官方 Compose 当前使用 louislam/dockge:1,默认 Web 端口 5001,并要求 stacks 目录左右挂载路径保持完全一致。

bash · 官方安装流程
sudo mkdir -p /opt/stacks /opt/dockge
cd /opt/dockge

sudo curl -L \
  https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml \
  -o compose.yaml

sudo docker compose up -d
sudo docker compose ps
Dockge 官方 Web 管理界面
Dockge 官方界面。后续每一个服务都可以作为独立 Stack 管理。
bash · 验证
curl -I http://127.0.0.1:5001
docker ps --filter name=dockge
预期结果浏览器打开 http://服务器IP:5001 可以进入 Dockge 初始化页面;容器状态为 Up。
安全提醒Dockge 挂载了 Docker Socket,拥有很高的主机控制能力。完成 NPM 反代后,不建议继续把 5001 裸露给整个互联网。

在 Dockge 创建 Nginx Proxy Manager 栈

目标让 NPM 成为唯一的 HTTP/HTTPS 公网入口。

在 Dockge 点击 Compose → New Stack,名称建议填写 npm,然后写入:

yaml · compose.yaml
services:
  app:
    image: jc21/nginx-proxy-manager:2.15.1
    container_name: nginx-proxy-manager
    restart: unless-stopped
    ports:
      - "80:80"
      - "81:81"
      - "443:443"
    environment:
      TZ: "Asia/Shanghai"
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

点击 Deploy。NPM 官方当前 Quick Setup 仍使用 80、81、443,其中 81 是管理 UI。

Nginx Proxy Manager Proxy Hosts 官方截图
NPM 官方 Proxy Hosts 页面。以后所有子域名都从这里建立。
bash · 验证端口
sudo ss -lntp | grep -E ':(80|81|443)\b'
curl -I http://127.0.0.1:81
完成标准80、81、443 都由 NPM 占用,访问 http://服务器IP:81 能打开管理界面。

部署 MyIP,并把真实域名加入允许列表

目标启动 MyIP,并避免反代后出现 403。

MyIP 当前官方文档明确要求真实域名场景配置 ALLOWED_DOMAINS;完整地理位置和 ASN 查询还需要免费的 MaxMind GeoLite2 凭据。

yaml · Dockge Stack
services:
  myip:
    image: jason5ng32/myip:latest
    container_name: myip
    restart: always
    ports:
      - "18966:18966"
    environment:
      ALLOWED_DOMAINS: "ip.example.com"
      MAXMIND_ACCOUNT_ID: "YOUR_ACCOUNT_ID"
      MAXMIND_LICENSE_KEY: "YOUR_LICENSE_KEY"
      MAXMIND_AUTO_UPDATE: "true"
MyIP IPCheck.ing 官方项目预览图
MyIP / IPCheck.ing 官方项目预览。
bash · 验证
curl -I http://127.0.0.1:18966
docker logs --tail=50 myip
如果反代后返回 403第一项就检查 ALLOWED_DOMAINS 是否和实际访问域名完全一致。

部署 IT-Tools 工具箱

目标启动 IT-Tools,并把容器 80 映射到宿主机 8088。
yaml · Dockge Stack
services:
  it-tools:
    image: corentinth/it-tools:latest
    container_name: it-tools
    restart: unless-stopped
    ports:
      - "8088:80"
IT-Tools 官方项目图
IT-Tools 官方项目图。适合自托管常用开发、文本、编码、网络转换工具。
bash · 验证
curl -I http://127.0.0.1:8088
docker ps --filter name=it-tools
完成标准本机 8088 能返回页面,容器保持 Up。

在 NPM 创建 Proxy Host,并申请 HTTPS

目标把 MyIP、IT-Tools 和 Dockge 从“IP:端口”切换成独立 HTTPS 域名。

进入 NPM:Hosts → Proxy Hosts → Add Proxy Host

Nginx Proxy Manager 新增 Proxy Host 官方截图
NPM 官方新增 Proxy Host 页面。Domain、Forward Host、Forward Port 是最关键的三个字段。
域名SchemeForward HostPort
ip.example.comhttp宿主机可达地址18966
tools.example.comhttp宿主机可达地址8088
dockge.example.comhttp宿主机可达地址5001

然后切到 SSL 标签:

  • Request a new SSL Certificate
  • Force SSL
  • HTTP/2 Support
  • 同意 Let's Encrypt 条款
bash · HTTPS 验证
curl -I https://ip.example.com
curl -I https://tools.example.com
curl -I https://dockge.example.com
Docker 里的 127.0.0.1 不是宿主机NPM 在容器中运行时,127.0.0.1 指向 NPM 容器自己。可通过共享 Docker network,或配置 host.docker.internal:host-gateway 访问宿主机服务。

安装 3X-UI,并先只验证面板本身

目标安装 3X-UI,确认面板端口和 Web Base Path,再做反向代理。
bash · 官方安装脚本
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/master/install.sh)

x-ui

安装后通过菜单确认:

配置说明
webPort当前官方默认值为 2053,实际以你的配置为准
webBasePath建议使用随机、非默认路径
webCertFile / webKeyFile如果 TLS 交给 NPM,这里可以不配置
3X-UI 官方 Overview 管理界面
3X-UI 官方 Overview 页面。先确认管理面板本身正常,再继续接 NPM。
bash · 验证监听
sudo ss -lntp | grep ':2053' || true
curl -I http://127.0.0.1:2053
管理面板不要长期裸露公网官方文档建议保留随机 Web Base Path,并使用 TLS;本文采用 NPM 在外层终结 HTTPS。

用 NPM 反向代理 3X-UI,并开启 WebSocket

目标通过 https://panel.example.com 访问面板,隐藏真实管理端口。

3X-UI 当前官方文档明确说明:面板实时更新依赖 WebSocket,因此反向代理必须正确处理 Upgrade/Connection。

NPM 字段填写值
Domain Namespanel.example.com
Schemehttp
Forward Hostname / IPNPM 能访问宿主机的地址
Forward Port2053 示例
Websockets Support开启

SSL 标签继续申请 Let's Encrypt 并开启 Force SSL。

BrowserHTTPS :443
NPMTLS + WebSocket
3X-UIHTTP :2053
bash · 验证
curl -I https://panel.example.com
curl -I https://panel.example.com/你的WebBasePath/
完成标准HTTPS 证书正常,页面能登录,实时状态正常刷新,浏览器不再直接访问 :2053

收口公网端口:只留下真正需要的入口

目标把管理端口和业务端口从公网攻击面中移除。
端口最终建议
80 / 443公网开放,交给 NPM
81仅可信 IP / VPN / 内网访问
5001仅 NPM 或可信网络访问
18966不作为公网入口
8088不作为公网入口
2053不作为公网入口
bash · 最终监听检查
sudo ss -lntp | grep -E ':(80|81|443|5001|18966|8088|2053)\b'
docker ps --format 'table {{.Names}}\t{{.Ports}}\t{{.Status}}'
更严格的做法在 Compose 中把仅供反代的服务绑定到 127.0.0.1:端口:容器端口,或者全部加入 NPM 的共享 Docker network,减少宿主机公开监听。

最终验收:不要只看“页面能打开”

目标逐项证明容器、反向代理、证书、域名和持久化都正常。
  • docker compose ps / Dockge 中所有 Stack 状态正常。
  • 每个子域名 HTTPS 返回正常,不出现证书警告。
  • NPM Proxy Hosts 状态 Online。
  • MyIP 不出现 403,MaxMind 功能可用。
  • IT-Tools 能实际打开一个工具并正常操作。
  • 3X-UI 登录和实时状态正常,WebSocket 没有断开。
  • 重启服务器或容器后,所有服务能自动恢复。
  • /opt/stacks、NPM data/letsencrypt 等持久化目录已备份。
bash · 一次性健康检查
for url in \
  https://dockge.example.com \
  https://ip.example.com \
  https://tools.example.com \
  https://panel.example.com; do
  echo "== $url =="
  curl -sS -o /dev/null -w '%{http_code} %{ssl_verify_result}\n' "$url"
done

故障排查:按现象定位,不要反复重装

现象常见原因检查 / 修复
NPM 启动失败80/81/443 被占用ss -lntp 找到占用进程;只能保留一个公网反代入口
NPM 502 Bad GatewayForward Host / Port 不可达从 NPM 容器内测试后端地址;不要误用容器内 127.0.0.1
MyIP 403ALLOWED_DOMAINS 未配置加入实际访问域名并重启 MyIP
MyIP 地理数据 503缺 MaxMind 凭据配置 GeoLite2 Account ID / License Key
3X-UI 页面能开但状态不刷新WebSocket 未代理NPM 开启 Websockets Support,确认代理链路支持 Upgrade
HTTPS 申请失败DNS 未生效或 80 被其它服务截获dig 检查 IP;确认 NPM 能收到 ACME HTTP Challenge
重启后数据消失Compose 没有正确持久化检查 volume 路径并备份 /opt/stacks 与应用 data 目录

部署完成后的结构

80/443 → Nginx Proxy Manager → Dockge / MyIP / IT-Tools / 3X-UI

Dockge 官方 Compose:louislam/dockge · NPM:nginxproxymanager.com · MyIP:jason5ng32/MyIP · IT-Tools:CorentinTh/it-tools · 3X-UI:MHSanaei/3x-ui

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!

一台服务器部署多个服务:Dockge + Nginx Proxy Manager + 3X-UI 端口复用与 HTTPS 教程
/archives/one-server-multi-services-dockge-npm-3xui
作者
Jayki
发布于
2026-08-30
许可协议
CC BY-NC-SA 4.0

评论

欢迎来到我的博客!