You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

docker-compose中如何实现app流量走VPN且可访问同环境其他服务

解决方案

核心问题原因

你之前遇到的问题本质是两点:

  1. 当app使用network_mode: service:vpn共享网络栈时,端口映射仅对网络栈所属的vpn服务生效,app自身的ports配置会被Docker忽略
  2. VPN客户端启动后默认会覆盖容器的DNS配置为VPN侧DNS,同时修改默认路由让所有流量走VPN隧道,导致Docker内网服务名无法解析、同栈服务的访问流量被导到VPN侧无法到达。

最终配置方案

第一步:修改docker-compose.yml配置

# docker-compose.yml
version: "3.7"

services:
  app:
    build: ./app
    depends_on:
      - db
      - vpn
    network_mode: "service:vpn" # 保留共享vpn网络栈
  db:
    image: postgres
  vpn:
    build: ./vpn
    cap_add:
      - NET_ADMIN
    ports:
      - "3001:3000" # 端口映射移到vpn服务下
    dns:
      - 127.0.0.11 # 优先使用Docker内置DNS,保证内部服务名可解析
      - 114.114.114.114 # 可替换为你常用的公共DNS或VPN侧DNS
    depends_on:
      - db

第二步:修改VPN容器启动脚本,添加内网路由规则

在VPN连接建立逻辑执行前后添加以下路由规则,保证Docker内网网段流量不走VPN隧道:

# 提取当前容器的Docker网关地址
DOCKER_GATEWAY=$(ip route list default | awk '{print $3}' | head -n 1)
# 添加Docker常用私有网段路由,走原生Docker网关
ip route add 172.16.0.0/12 via ${DOCKER_GATEWAY} dev eth0
ip route add 192.168.0.0/16 via ${DOCKER_GATEWAY} dev eth0
ip route add 10.0.0.0/8 via ${DOCKER_GATEWAY} dev eth0

如果使用OpenVPN作为VPN客户端,也可以直接在OpenVPN配置文件中添加以下规则,无需修改启动脚本:

route 172.16.0.0 255.240.0.0 net_gateway
route 192.168.0.0 255.255.0.0 net_gateway
route 10.0.0.0 255.0.0.0 net_gateway

验证方式

启动服务后进入app容器执行以下命令验证:

  1. 执行ping db,可正常解析并连通即内部服务访问正常
  2. 执行curl ifconfig.me,返回IP为VPN出口IP即公网流量走VPN隧道正常
  3. 宿主机访问http://localhost:3001可正常打开app服务即端口映射正常

内容的提问来源于stack exchange,提问作者fiedl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 03:45:05