Docker如何实现容器之间的通信
在 Docker 中,实现容器之间的通信有多种方式,核心在于网络配置。下面我从 基础原理、常见方式、最佳实践、以及 docker-compose
方式 全面讲解。
一、Docker 容器间通信的本质是什么?
容器之间通信依赖 Docker 网络(Network),默认有几种网络类型:
类型 | 描述 |
---|---|
bridge | 默认网络,同一网桥内容器可以通过容器名通信 |
host | 共享宿主机网络,无隔离(无端口映射) |
none | 容器无网络,仅用于极端隔离场景 |
overlay | 用于 Docker Swarm 集群通信 |
二、常用容器通信方式
🧱 1. **桥接网络(默认)**下的通信
✔ 方法一:通过容器名称访问
默认容器在 bridge 网络中可以通过 名称解析容器名 → IP 进行通信:
docker network create mynet
docker run -dit --name container-a --network mynet alpine sh
docker run -dit --name container-b --network mynet alpine sh
然后进入 container-b
,ping container-a
即可:
ping container-a
👉 可用于微服务中服务间调用,如:
http://container-a:8080/api/...
方法二:共享同一网络(如 docker-compose 自动创建)
version: '3'
services:web:image: nginxapp:image: my-java-appdepends_on:- web
web
的容器名称就是web
app
中可通过web:80
与其通信,无需指定 IP
2. host 网络模式下通信
容器共享宿主机网络,无端口映射限制,适合需要 UDP、低延迟通信:
docker run --network host my-app
注意:
- 所有容器共享端口空间,避免端口冲突
- 容器可以通过
localhost
访问宿主其他服务
3. 端口暴露 + 宿主机 IP 通信(最通用但低效)
每个容器通过 -p
映射端口暴露到宿主机:
docker run -p 8080:8080 --name web my-web
docker run -p 8081:8081 --name app my-app
此时容器间不能直接通信,只能通过宿主 IP 和端口:
curl http://host-ip:8080/
三、Docker 网络命令速查
命令 | 说明 |
---|---|
docker network ls | 查看所有网络 |
docker network inspect mynet | 查看某网络下容器信息(IP等) |
docker network create mynet | 创建自定义网络 |
docker network connect | 把容器加入到一个网络 |
docker network disconnect | 移除容器的网络连接 |
四、docker-compose 中容器通信最佳实践
version: '3'
services:mysql:image: mysqlenvironment:MYSQL_ROOT_PASSWORD: 123456app:image: my-java-appdepends_on:- mysqlenvironment:DB_HOST: mysql
- app 可以用
mysql:3306
与数据库通信 - 不用写 IP,容器名即服务名,Compose 默认建立 bridge 网络
五、最佳实践小结
场景 | 推荐方案 |
---|---|
同机通信 | 自定义 bridge 网络,容器名互通 |
简化开发 | 用 docker-compose 管理服务 |
性能要求高 | 使用 --network host |
集群通信 | 使用 overlay 网络(Docker Swarm) |
补充:容器 DNS 是怎么解析的?
Docker 默认为每个网络分配一个 DNS 服务,容器名在网络中解析为容器 IP:
# 容器内
nslookup web
你会看到:web
自动解析成 IP 地址。
总结
通信方式 | 说明与特点 |
---|---|
通过容器名通信 | 推荐,自定义网络或 docker-compose 默认支持 |
宿主机 IP + 映射端口 | 最通用但性能差 |
host 网络通信 | 高性能但需管理端口冲突 |
overlay 网络通信 | 多主机通信(Swarm/集群用) |