在 Docker Compose 中,网络既是容器通信的通道,也是服务隔离的边界。很多项目在开发阶段只使用默认网络,部署后却遇到服务名无法解析、跨项目访问失败、数据库意外暴露等问题。本文从默认网络、分层隔离、跨项目共享网络和故障排查四个方面,给出一套可直接落地的实践方案。🚀
一、理解 Compose 默认网络
执行 docker compose up -d 时,如果配置文件没有显式声明网络,Compose 会为当前项目创建一个默认的 bridge 网络,名称通常为“项目名_default”。同一项目中的服务会自动加入该网络,并可通过服务名相互访问。具体机制可参考 Docker Compose 网络官方文档。
例如,应用服务名为 app,数据库服务名为 db,那么 app 应使用 db:5432 连接数据库,而不是填写数据库容器的动态 IP。容器重建后 IP 可能变化,但服务名通常保持稳定。需要特别注意,容器之间通信使用的是容器端口,而宿主机访问容器时才使用 ports 映射后的主机端口。
实用原则:容器内部优先使用“服务名加容器端口”,不要依赖固定 IP,也不要把 localhost 当成其他容器。
二、使用多网络实现服务隔离
默认网络会让项目内所有服务处于同一通信范围。对于包含反向代理、业务接口和数据库的系统,更推荐划分 frontend 与 backend 两个网络:代理和接口加入 frontend,接口和数据库加入 backend。这样代理无法直接连接数据库,数据库也不必进入面向入口服务的网络。🔐
配置思路如下:
services:
proxy:
networks: [frontend]
api:
networks: [frontend, backend]
db:
networks: [backend]
networks:
frontend:
backend:
internal: true
其中,api 是连接两个网络的中间服务;proxy 与 db 因为没有共享网络,不能直接通过容器网络通信。为 backend 设置 internal: true,还可进一步限制该网络的外部连通能力。网络相关字段及行为可查看 Compose networks 配置参考。
网络隔离不能替代身份认证、访问控制和防火墙,但它能够缩小容器被入侵后的横向移动范围。数据库、缓存、消息队列等内部组件如果不需要被宿主机或外部客户端访问,就不要配置 ports;同一 Docker 网络中的应用仍可直接访问其容器端口。
三、让不同 Compose 项目安全通信
不同目录或不同项目名启动的 Compose 应用,默认会进入各自独立的网络,因此项目 A 无法直接通过服务名访问项目 B。需要跨项目通信时,可以预先创建一个共享网络,再由两个项目通过 external: true 引用。
第一步,创建共享网络:
docker network create shared_gateway
第二步,在两个 compose.yaml 中分别声明:
networks:
shared_gateway:
external: true
name: shared_gateway
第三步,只让确实需要互通的服务加入该网络:
services:
web:
networks:
- default
- shared_gateway
这种模式常用于独立部署的反向代理连接多个业务项目。共享网络由外部创建,不属于单个 Compose 项目的生命周期,因此执行 docker compose down 时通常不会删除它。如果外部网络不存在,Compose 会直接报错,而不会根据 external 声明自动创建。⚙️
避免跨项目服务名冲突
当多个项目在共享网络中都存在 web、api 或 db 等常见服务名时,DNS 名称可能产生混淆。建议为共享网络配置清晰的网络别名,例如 order-api、member-api,并让调用方使用别名访问。别名应体现系统和服务用途,同时避免依赖 container_name,因为固定容器名会增加扩容和多环境部署时的冲突风险。
四、跨项目通信的排查步骤
- 执行 docker network ls,确认目标网络真实存在且名称正确。
- 执行 docker network inspect shared_gateway,检查通信双方是否都已连接。
- 进入调用方容器,使用 getent hosts 服务名 验证 Docker DNS 解析。
- 使用 curl、wget 或 nc 测试目标服务的容器端口,不要误用主机映射端口。
- 检查目标进程是否监听 0.0.0.0,若只监听 127.0.0.1,其他容器通常无法访问。
- 检查应用协议、TLS 设置、健康状态和日志,区分“网络不通”与“应用拒绝连接”。
临时验证时,还可以执行 docker network connect shared_gateway 容器名,把运行中的容器接入共享网络;验证结束后使用 docker network disconnect 移除连接。不过正式环境应把网络关系写入 compose.yaml,避免容器重建后手工配置丢失。🧰
总结
Compose 网络治理可以归纳为三条:项目内部使用服务名通信,按访问路径拆分前端与后端网络,跨项目场景通过预创建的 external 网络共享连接。与此同时,应尽量减少 ports 暴露、避免固定 IP、谨慎设置网络别名,并用 network inspect、DNS 查询和端口测试逐层排障。合理的网络设计不仅能解决“容器如何互通”,还能够明确“哪些容器不应该互通”,让部署结构更安全、更清晰,也更容易维护。✅