如何从非指定network_mode的容器获取该模式下容器IP并通过名称通信
问题原因
- 你配置了
first容器使用network_mode: service:vpn,意味着first和vpn完全共享网络栈,first本身没有独立的网络命名空间,Docker内置DNS服务只会为拥有独立网络栈的服务自动注册域名记录,因此second容器无法通过DNS解析到first的域名。 first能正常解析second的原因是vpn服务本身在Docker默认网桥中有独立网络栈,可正常查询到同网桥下second的DNS记录,first共享该网络栈因此继承了解析能力。- 额外需注意:VPN启动后添加了全局默认路由走隧道,会导致
vpn回给同网桥下second的数据包被路由到VPN隧道,即使解析到IP也会出现通信失败的情况。
解决方案
核心配置调整
- 给
vpn服务在同网桥下配置别名first,second解析first域名时就会自动指向vpn的IP,因为first共享vpn的网络栈,访问vpn的IP就等于访问first的服务。 - 给
vpn容器添加静态路由规则,指定Docker网桥网段的流量走原有局域网网关,避免回包被导到VPN隧道丢失。
修改后的docker-compose.yml示例
version: '3.9' services: vpn: build: ./vpn container_name: vpn env_file: - ss.env cap_add: - NET_ADMIN - NET_RAW devices: - /dev/net/tun:/dev/net/tun dns: - 1.1.1.1 # 配置网络别名,让second解析first时直接指向vpn的IP networks: default: aliases: - first # 先添加静态路由再启动VPN,192.168.144.0/24和你日志中的网关网段匹配 command: sh -c "ip route add 192.168.144.0/24 via 192.168.144.1 && 替换为你原有VPN服务的启动命令" # 可选:暴露first使用的端口,同网桥下不暴露也可互通,加了更规范 expose: - 37020 first: build: ./first container_name: first depends_on: - vpn network_mode: service:vpn second: build: ./second container_name: second depends_on: - vpn
通用化优化(可选)
如果不想硬编码Docker网桥网段,可将路由命令替换为自动识别版本,适配不同Docker环境:
ip route add $(ip route show default | awk '{print $3}' | cut -d '.' -f 1-3).0/24 via $(ip route show default | awk '{print $3}')
验证方式
部署完成后进入second容器执行ping first可正常连通,原有Python脚本无需修改即可直接通过容器名互发数据。
内容的提问来源于stack exchange,提问作者Vieira
相关产品推荐
相关产品推荐

