6月6日 20:29

Docker 容器间怎么通信?同一项目、跨项目和跨主机方案

两个容器要互相访问,怎么连通?同一个 compose 项目的容器用服务名直接访问,不同项目的容器需要共享网络,跨主机通信就得用 Overlay 网络。这篇按场景从简单到复杂讲清楚。

同一 docker-compose 项目:默认网络

Docker Compose 自动为每个项目创建一个网络,项目内的容器可以互相用服务名访问:

yaml
# docker-compose.yml services: api: image: myapp-api ports: - "3000:3000" redis: image: redis:7 postgres: image: postgres:16
bash
# api 容器内直接用服务名访问 curl http://redis:6379 # 访问 Redis curl http://postgres:5432 # 访问 PostgreSQL

不需要 IP,不需要 --link——Docker 内置 DNS 自动把服务名解析为容器 IP。

自定义网络名

默认网络名是 项目名_default。如果要自定义:

yaml
services: api: networks: - frontend - backend redis: networks: - backend networks: frontend: backend:

api 同时在 frontend 和 backend 两个网络里——可以访问两边。redis 只在 backend 里——frontend 网络的容器访问不到 redis,实现网络隔离。

不同 docker-compose 项目:外部网络

两个独立的 compose 项目需要通信时,共享一个外部网络:

bash
# 创建共享网络 docker network create shared-net
yaml
# 项目 A: docker-compose.yml services: api: networks: - shared-net networks: shared-net: external: true
yaml
# 项目 B: docker-compose.yml services: worker: networks: - shared-net networks: shared-net: external: true

项目 A 的 api 和项目 B 的 worker 通过服务名互相访问。

容器访问宿主机

容器里需要访问宿主机上的服务(比如宿主机上的 MySQL):

bash
# 专用 DNS 名 curl http://host.docker.internal:3306

host.docker.internal 是 Docker Desktop 提供的特殊 DNS,自动解析为宿主机 IP。Linux 上需要手动添加:

yaml
services: api: extra_hosts: - "host.docker.internal:host-gateway"

容器间直接用 IP

不推荐但有时需要:

bash
# 查看容器 IP docker inspect myapp --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' # 查看所有容器的 IP docker network inspect bridge --format '{{range .Containers}}{{.Name}}: {{.IPv4Address}}{{end}}'

容器 IP 每次重启可能变化——硬编码 IP 是反模式,应该用服务名或 DNS。

端口映射:容器对外暴露服务

yaml
services: api: ports: - "3000:3000" # 宿主机 3000 → 容器 3000 - "8080:80" # 宿主机 8080 → 容器 80 - "127.0.0.1:3306:3306" # 只允许本机访问

127.0.0.1:3306:3306 这种写法限制了只监听 loopback 接口——外部无法访问,只有宿主机本身可以连。适合数据库等不需要对外暴露的服务。

端口冲突排查

bash
# 查看宿主机端口占用 lsof -i :3000 # 或 ss -tlnp | grep 3000 # Docker 占用的端口 docker port myapp

网络模式选择

模式说明适用场景
bridge(默认)容器有独立 IP,通过 NAT 访问外部大部分场景
host容器直接用宿主机网络栈,无隔离需要极致网络性能
none无网络离线计算任务
overlay跨主机容器通信Docker Swarm / 多主机

host 模式

yaml
services: api: network_mode: host

host 模式下容器没有独立 IP,直接用宿主机的端口和网络。好处是没有 NAT 性能损耗,坏处是端口冲突风险高(容器和宿主机共享端口空间)。

不要在生产环境用 host 模式——失去了网络隔离,一个容器被攻破等于宿主机被攻破。

跨主机通信:Overlay 网络

Docker Swarm 多主机环境下,不同主机上的容器需要通信:

bash
# 创建 Overlay 网络 docker network create -d overlay my-overlay # 在 Overlay 网络上启动服务 docker service create --network my-overlay --name api myapp docker service create --network my-overlay --name worker myworker

Overlay 网络底层用 VXLAN 隧道——api 和 worker 即使跑在不同的物理机上,也能通过服务名直接通信,和单机体验一致。

DNS 排查

容器间访问不通时,先排查 DNS:

bash
# 进入容器测试 DNS 解析 docker exec myapp nslookup redis docker exec myapp ping redis # 查看 DNS 配置 docker exec myapp cat /etc/resolv.conf # 临时指定 DNS docker run --dns 8.8.8.8 myapp

常见问题:自定义了 docker-compose.ymlnetworks 但忘了在服务里引用,或者两个服务不在同一个网络里。

标签:Docker