一、当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是默认网络,它的工作机制很有意思:

  1. 使用私有IP段172.17.0.0/16
  2. 通过NAT与宿主机通信
  3. 容器间通过虚拟网卡互联

但问题就出在这个默认配置上。当多个项目共用默认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

常见误区:

  1. 认为--network和-p参数冲突(实际可以配合使用)
  2. 在docker-compose中混合使用默认网络和自定义网络
  3. 忘记不同网络间的容器默认不能通信

七、总结与展望

Docker网络就像城市交通系统,默认配置相当于主干道,而自定义网络就像专用车道。经过这些年的实践,我总结出几个关键点:

  1. 重要服务一定要用独立网络
  2. 跨主机通信考虑overlay网络
  3. 网络问题多查iptables和DNS配置
  4. 善用docker network inspect命令

未来随着服务网格(Service Mesh)的普及,Docker网络可能会变得更"智能"。但无论如何,理解底层原理永远是最重要的。