Docker --link容器重启后IP未刷新导致服务发现失败
· 开发
适用环境
- Docker 1.13 ~ 19.03,使用
--link做容器间通信的老旧部署方式
问题现象
使用 docker run --link mysql:db 启动业务容器,业务通过主机名 db 连接MySQL。
MySQL容器故障重启,IP地址发生改变;业务容器依旧连接旧IP,报 Connection refused。
排查过程
- 进入业务容器查看hosts:
cat /etc/hosts
发现 db 对应的IP是MySQL重启之前的旧地址。
2. 重启业务容器,/etc/hosts 才会更新为新IP。
3. 查阅Docker官方文档:--link 只在容器启动时刻静态写入hosts,运行期不会动态更新。
根本原因
--link 原理:容器启动阶段往双方 /etc/hosts 写入静态域名‑IP映射。依赖容器IP固定不变。
Docker默认bridge网络,容器重启会重新分配IP,静态hosts条目直接失效。
解决方案
方案一:使用自定义桥接网络 User‑defined bridge(推荐)
# 创建自定义网络
docker network create mynet
# 启动mysql,加入自定义网络
docker run --net=mynet --name mysql mysql:5.7
# 启动业务容器,加入同一个网络
docker run --net=mynet --name app myapp
自定义网络内置Docker DNS,容器名可以直接作为主机名,容器重启IP变化DNS自动同步。
方案二:Docker Compose
compose默认创建自定义网络,服务名直接做域名,自动动态解析。
方案三:引入服务注册发现
- K8s环境使用Service+Endpoint
- Swarm/Consul使用注册中心做服务发现
生产建议
--link 已经被Docker标记为legacy遗留特性,新项目禁止使用。容器之间通信统一使用自定义网络+DNS解析。