使用 Docker 部署 3x-ui 并配置 VPN 节点 使用新ip

写给新管理员:本文基于真实踩坑经验整理而来,请从头到尾阅读一遍再开始操作,能帮你避开 80% 的常见问题。

此文档根据Qingwen和ChatGPT沟通部署成功后的聊天记录 由Claude Sonnet 4.6总结而成


背景与架构说明

3x-ui 是一个基于 Xray 的图形化管理面板,可以方便地创建和管理代理节点(VMess / VLESS / Trojan / Reality 等协议)。

本文的使用场景:

  • 外区家里内网的 Windows 电脑上运行 Docker 容器
  • 管理员通过本机浏览器访问面板
  • 自己/他人通过公网连接代理节点实现安全访问外区家里ip地址网络

最终网络架构如下:

[ 管理员 ]
    ↓ 内网访问 (127.0.0.1:2053)
[ 3x-ui 面板 ]
    ↓ 配置
[ Xray 代理节点 ]
    ↑ 公网连接 (443 端口)
[ 自己/他人 ]

重要原则:面板(admin UI)永远不对外暴露,只有代理节点端口对外开放。


前置条件

在开始之前,确认以下条件均已满足:

  • 公网 IP:访问 https://ifconfig.me,确认显示的 IP 与路由器后台 WAN IP 一致,否则说明你在运营商 NAT 后面,需要向运营商申请公网 IP 或改用云服务器
  • 路由器管理权:需要配置端口转发(Port Forwarding)
  • WindowsLinux 主机,已安装 Docker 和 Docker Compose

一、Windows 部署

1.1 关键注意:network_mode: host 在 Windows 不可用

这是 Windows 上最常见的坑。在 Linux 原生 Docker 中,network_mode: host 让容器直接共享宿主机网络。但在 Windows Docker Desktop 中,Docker 实际运行在一个内部虚拟机里:

Windows 宿主机
    ↓
Docker 虚拟机 (Linux)
    ↓
你的容器

因此容器监听的端口不是 Windows 的 localhost。如果你看到日志显示:

INFO - Web server running HTTP on [::]:2053

但浏览器访问 http://localhost:2053 却无法连接,就是这个原因。

解决方法:删除 network_mode: host,改用显式端口映射。

1.2 docker-compose.yml 配置

创建工作目录(例如 C:\3xui),在其中新建 docker-compose.yml

services:
  3xui:
    image: ghcr.io/mhsanaei/3x-ui:latest
    container_name: 3xui_app
    volumes:
      - $PWD/db/:/etc/x-ui/      # persist panel database
      - $PWD/cert/:/root/cert/   # TLS certificate directory
    environment:
      XRAY_VMESS_AEAD_FORCED: "false"
      XUI_ENABLE_FAIL2BAN: "true"
    ports:
      # Panel: local-only access, not exposed to the internet
      - "127.0.0.1:2053:2053"
      # VPN node port, exposed to the internet
      - "443:443"
      # (Optional) HTTP port, can be removed if not needed
      - "80:80"
      - "2096:2096"   # for sharing subscription links port
    restart: unless-stopped

端口说明

  • 127.0.0.1:2053:2053:面板端口,仅本机可访问,外网完全无法到达
  • 443:443:代理节点端口,对外开放
  • 2096:2096:订阅链接端口,对外开放 (Optional: 如果需要分享订阅链接; 如果使用,需要和443一样操作 接下来的Window防火墙,路由器端口转发)

1.3 启动服务

打开 PowerShell(或 CMD),切换到 docker-compose.yml 所在目录:

# Start service in detached mode
docker compose up -d

# Verify container is running
docker ps

# Check which ports are mapped
docker port 3xui_app

# View live logs
docker compose logs -f

服务正常启动后,在本机浏览器访问:

http://127.0.0.1:2053

默认用户名/密码通常为 admin / admin,首次登录后立即修改


二、Linux 部署(Debian / Ubuntu)

Linux 上的 Docker 原生支持 network_mode: host,但为了保持一致性和可控性,同样推荐使用端口映射方式

2.1 安装 Docker(如未安装)

# Install prerequisites
sudo apt update
sudo apt install -y ca-certificates curl gnupg

# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine and Compose
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# (Optional) Allow running Docker without sudo
sudo usermod -aG docker $USER
newgrp docker

Debian 用户将上面的 ubuntu 换成 debian 即可,其余步骤相同。

2.2 部署 3x-ui

# Create working directory
mkdir -p ~/3xui && cd ~/3xui
mkdir -p db cert

# Create docker-compose.yml
cat > docker-compose.yml << 'EOF'
services:
  3xui:
    image: ghcr.io/mhsanaei/3x-ui:latest
    container_name: 3xui_app
    volumes:
      - ./db/:/etc/x-ui/
      - ./cert/:/root/cert/
    environment:
      XRAY_VMESS_AEAD_FORCED: "false"
      XUI_ENABLE_FAIL2BAN: "true"
    ports:
      - "127.0.0.1:2053:2053"   # panel: local-only
      - "443:443"                # VPN node port
      - "80:80"                  # optional HTTP port
    restart: unless-stopped
EOF

# Start the service
docker compose up -d

2.3 Linux 特有:防火墙设置(UFW)

如果系统启用了 UFW:

# Allow VPN node port
sudo ufw allow 443/tcp

# Do NOT expose panel port (2053) to the public
# 127.0.0.1:2053 binding already handles this at Docker level

sudo ufw status

2.4 Linux 特有:设置开机自启

Docker 的 restart: unless-stopped 已经处理容器重启,但需要确保 Docker 服务本身开机自启:

sudo systemctl enable docker
sudo systemctl start docker

三、Windows 防火墙配置

即使 Docker 已经绑定了端口,Windows 防火墙仍然可能拦截外部流量,需要手动添加入站规则。

方法一:图形界面

  1. Win + R,输入 wf.msc 打开高级防火墙设置
  2. 点击左侧 Inbound Rules(入站规则)
  3. 右侧点击 New Rule…
  4. 类型选 Port → Next
  5. TCP,端口填 443 → Next
  6. Allow the connection → Next
  7. 三个 Profile(Domain / Private / Public)全部勾选 → Next
  8. 名称填 xray-443 → Finish

方法二:PowerShell(快捷)

以管理员身份运行 PowerShell:

# Add inbound rule for port 443 (TCP)
New-NetFirewallRule `
  -DisplayName "xray-443" `
  -Direction Inbound `
  -Protocol TCP `
  -LocalPort 443 `
  -Action Allow

# Verify the rule was created
Get-NetFirewallRule -DisplayName "xray-443"

验证端口是否正在监听:

# Should show "0.0.0.0:443 LISTENING"
netstat -ano | findstr :443

四、路由器端口转发

如果服务器在外区家里内网,还需要在路由器上将公网流量转发到这台机器。

4.1 获取内网 IP

# Windows
ipconfig
# Find "IPv4 Address" under the active adapter, e.g. 192.168.1.100
# Linux
ip addr show | grep "inet "
# or
hostname -I

4.2 在路由器设置端口转发

登录路由器管理页(通常是 192.168.1.1),找到 端口转发 / Virtual Server / NAT 相关设置,添加如下规则:

字段
External Port(外部端口) 443
Internal IP(内网 IP) 你的机器 IP,如 192.168.1.100
Internal Port(内部端口) 443
Protocol(协议) TCP(不要选 ALL,部分路由器有 bug)
Status(状态) Enabled

强烈建议:在路由器的 DHCP 地址保留(Address Reservation)功能里,将这台机器的 MAC 地址与 IP 绑定,防止 DHCP 重新分配 IP 后端口转发失效。

A successful setup example: Successful setup example

4.3 验证端口是否开放

非局域网网络(如手机 4G)上,访问以下地址测试: https://www.yougetsignal.com/tools/open-ports/

输入你的公网 IP 和端口 443,显示 Open 即为成功。

注意:不要在同一个局域网内测试,因为路由器可能不支持 NAT loopback(内网绕回)。比如使用手机,关闭wifi后流量查询。


五、在 3x-ui 面板创建代理节点

以下操作均在面板英文界面中进行。

5.1 登录面板

http://127.0.0.1:2053

5.2 新建 Inbound

  1. 左侧菜单点击 Inbounds
  2. 点击 + Add Inbound

5.3 基础配置

字段
Protocol vless
Listen IP 0.0.0.0
Port 443
Remark office-vpn(任意命名)

5.4 添加客户端(每位自己/他人一个)

点击 Clients 区域,点击 + Add Client

字段
Email 自己/他人名称,如 myself
UUID 点击 Generate 自动生成

安全原则:每人分配独立 UUID,不要共用同一个 Client,这样可以单独吊销某人的访问权限。

5.5 Transmission 设置

Transmission 下拉菜单中选择:

TCP (RAW)

5.6 Security 设置(推荐:Reality)

Security 下拉菜单中选择 Reality,随后会出现 Reality 专属配置项:

字段
Dest (Target) www.microsoft.com:443
Server Names www.microsoft.com
Private Key / Public Key 点击 Get New Keys 自动生成
Short IDs 点击 Generate 自动生成
mldsa65 Seed / Verify 留空(实验性功能,现阶段不填)

为什么推荐 Reality 而不是普通 TLS?

对比 VLESS + None VLESS + TLS VLESS + Reality
加密
隐蔽性 ❌ 明文易识别 ⚠️ 较好 ✅ 伪装成正常 HTTPS
需要域名 不需要 需要 不需要
需要证书 不需要 需要 不需要
配置难度 简单 复杂 中等
适用场景 仅测试 有域名时 推荐

Reality 的核心优势在于:它让代理流量在网络监测层面看起来像是在访问 www.microsoft.com,而非明显的代理特征。

最后一步,点击 Save


六、向自己/他人分发配置

6.1 设置面板的对外 IP

由于面板只绑定了 127.0.0.1,它不知道你的真实公网 IP,导出的链接默认包含 127.0.0.1

需要在面板设置中指定公网 IP:

  1. 进入 Panel SettingsSystem Settings
  2. 找到 External Address / Public IP
  3. 填入你的公网 IP(如 81.123.123.12
  4. 保存

这样导出的链接会自动包含正确的 IP。

6.2 导出链接

在 Inbounds 列表中找到刚创建的节点,点击:

Export All URLs

会弹出类似格式的链接:

vless://UUID@81.123.123.12:443?type=tcp&security=reality&sni=www.microsoft.com&pbk=...&sid=...#office-vpn

将此链接发送给对应自己/他人。

如果你有多位人,点击具体 Client 行末尾的操作按钮,可以单独导出某个用户的链接。

6.3 连接方设备客户端配置

连接方根据设备安装对应客户端:

平台 客户端
Windows v2rayN(推荐最新版)
Android v2rayNG
iOS / macOS Shadowrocket

导入步骤

  1. 复制链接
  2. 打开客户端 → Import / 从剪贴板导入 / Scan QR
  3. 选中节点 → 连接

连接成功后,访问 https://ipinfo.iohttps://ifconfig.me,若显示 IP 变为你的公网 IP,则说明 VPN 已生效。


七、安全建议

按重要性排序:

✅ 必须做

  • 修改默认密码:首次登录面板后立即修改用户名和密码
  • 面板不对外暴露:使用 127.0.0.1:2053:2053 绑定,永远不要改成 0.0.0.0:2053:2053
  • 每人一个 UUID:便于独立管理和吊销

� 建议做

  • 设置流量限制(Total Flow):在 Client 编辑页面设置每人的流量上限,防止滥用
  • 设置有效期(Duration / Expiry):为临时用户设置到期时间
  • 固定内网 IP:在路由器 DHCP 地址保留中绑定机器 MAC,防止 IP 变化导致端口转发失效
  • 定期检查日志:面板 → Logs,观察是否有异常连接

立即在面板中:

Inbounds → 对应节点 → Edit Client → 选择对应用户 → Regenerate ID(重置 UUID)

新 UUID 生成后,旧链接立即失效。


八、常见问题排查

Q1:启动后 localhost:2053 访问不了

最可能原因docker-compose.yml 中使用了 network_mode: host(Windows 不支持)。

解决:删除 network_mode: host,改用 ports 映射。

Q2:防火墙和端口转发都配置了,外网还是连不上

按以下顺序排查:

# Step 1: Verify service is listening
netstat -ano | findstr :443
# Expected: 0.0.0.0:443  LISTENING

# Step 2: Verify public IP
curl https://ifconfig.me

# Step 3: Check router WAN IP matches ifconfig.me
# Login to 192.168.1.1 → WAN Status

# Step 4: Test from a non-LAN network (4G phone or remote machine)
# Use https://www.yougetsignal.com/tools/open-ports/

如果 Step 3 发现路由器 WAN IP 与 ifconfig.me 显示的 IP 不一致,说明你在运营商 NAT 后面,需要联系运营商申请公网 IP,或改用云服务器。

Q3:导出的链接里 IP 是 127.0.0.1

需要在面板 Panel Settings → External Address 中填入公网 IP,之后重新导出。

Q4:客户端提示 handshake error 或连接失败

常见原因:

  • 客户端版本不支持 Reality(请更新到最新版)
  • 链接中的 IP 仍是 127.0.0.1(见 Q3)
  • 路由器协议选了 ALL 而非 TCP(某些 TP-Link 路由器的 ALL 模式有 bug,请改为 TCP)

Q5:端口测试显示 Closed,但确信路由器已配置

检查以下几点:

  • 路由器端口转发的内网 IP 是否与 ipconfig 输出的 IPv4 一致
  • 协议是否选的是 TCP(不是 UDP 或 ALL)
  • 外部端口是否写的是 443(不是 433,注意数字)
  • 是否在同一局域网内测试(内网测试可能因 NAT loopback 不支持而失败)
*文档版本:v1.0 基于 3x-ui v2.8.11 + Xray 26.2.6*



Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • Ansible 多机自动化工具 初学笔记 - Kin_Zhang - 博客园
  • UE4/CARLA 启动崩溃排查 | Fix Vulkan Segmentation Fault on Linux