一、当Docker容器突然罢工时
最近不少小伙伴在群里吐槽:"明明昨天还能跑的容器,今天怎么就启动失败了?"这种问题十有八九和网络配置有关。Docker默认创建的bridge网络虽然方便,但就像小区里的公共WiFi,用的人多了难免出问题。
举个真实案例:某次我用Docker部署MySQL服务时,突然报错:
# 技术栈:Docker + MySQL
docker run -d --name mysql_db -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
# 报错信息:
Error response from daemon: failed to create endpoint mysql_db on network bridge:
Conflict, the name bridge is already reserved for default network
二、解剖Docker的默认网络
Docker安装时会自动创建三个网络:
docker network ls
# 输出示例:
NETWORK ID NAME DRIVER SCOPE
a1b2c3d4e5f6 bridge bridge local
f1e2d3c4b5a6 host host local
123456789abc none null local
其中bridge是默认网络,它的工作机制很有意思:
- 使用私有IP段172.17.0.0/16
- 通过NAT与宿主机通信
- 容器间通过虚拟网卡互联
但问题就出在这个默认配置上。当多个项目共用默认bridge时,就像把几十个公司的快递都堆在同一个收发室,难免会出现:
- IP地址冲突
- 端口映射混乱
- DNS解析异常
三、实战解决方案
方案1:创建自定义网络
# 创建自定义bridge网络
docker network create --driver bridge my_network
# 运行容器时指定网络
docker run -d --name mysql_db \
--network my_network \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7
# 验证网络配置
docker inspect mysql_db | grep IPAddress
方案2:修改默认网络配置
# 停止Docker服务
sudo systemctl stop docker
# 修改配置文件(Linux系统)
sudo vi /etc/docker/daemon.json
# 添加以下内容:
{
"bip": "192.168.100.1/24",
"default-gateway": "192.168.100.254",
"dns": ["8.8.8.8", "114.114.114.114"]
}
# 重启Docker
sudo systemctl start docker
方案3:使用host网络模式(适合性能敏感场景)
docker run -d --name nginx \
--network host \
nginx:latest
四、进阶网络故障排查
当问题发生时,可以按这个流程排查:
# 1. 检查容器状态
docker ps -a
# 2. 查看容器日志
docker logs [容器ID]
# 3. 检查网络连接
docker exec -it [容器ID] ping www.baidu.com
# 4. 测试端口连通性(示例测试MySQL端口)
docker exec -it mysql_db bash -c "apt update && apt install -y telnet && telnet 127.0.0.1 3306"
# 5. 检查iptables规则
sudo iptables -L -n -t nat
五、不同场景下的最佳实践
开发环境建议:
- 为每个项目创建独立网络
- 使用docker-compose管理网络
# docker-compose.yml示例
version: '3'
services:
web:
image: nginx
networks:
- mynet
db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: example
networks:
- mynet
networks:
mynet:
driver: bridge
ipam:
config:
- subnet: 172.22.0.0/24
生产环境建议:
- 禁用默认bridge网络
- 使用overlay网络实现多主机通信
- 配合Kubernetes的CNI插件
六、避坑指南
最近帮客户排查的一个典型问题:
# 错误操作:同时绑定主机端口和指定网络
docker run -d -p 3306:3306 \
--network my_network \
mysql:5.7
# 正确做法:先创建网络再运行容器
docker network create mysql_net
docker run -d --name mysql \
--network mysql_net \
-p 3306:3306 \
mysql:5.7
常见误区:
- 认为--network和-p参数冲突(实际可以配合使用)
- 在docker-compose中混合使用默认网络和自定义网络
- 忘记不同网络间的容器默认不能通信
七、总结与展望
Docker网络就像城市交通系统,默认配置相当于主干道,而自定义网络就像专用车道。经过这些年的实践,我总结出几个关键点:
- 重要服务一定要用独立网络
- 跨主机通信考虑overlay网络
- 网络问题多查iptables和DNS配置
- 善用docker network inspect命令
未来随着服务网格(Service Mesh)的普及,Docker网络可能会变得更"智能"。但无论如何,理解底层原理永远是最重要的。
评论