一、当Docker网络突然"失联"时

刚开始用Docker那会儿,我天真地以为容器网络就像家里的Wi-Fi,插上就能用。直到某天凌晨三点,我的微服务集群突然集体"失联",监控警报响得像过年放鞭炮似的。这才发现,Docker默认网络配置里藏着不少"坑"。

举个例子,用默认的bridge网络启动两个Nginx容器:

# 技术栈:Docker CLI
docker run -d --name nginx1 nginx:alpine  # 默认使用bridge网络
docker run -d --name nginx2 nginx:alpine

# 尝试在nginx1中ping nginx2 - 会直接失败!
docker exec -it nginx1 ping nginx2  # 提示:ping: bad address 'nginx2'

看到没?默认情况下,容器间居然不能通过容器名互访!这就像给同一栋楼的住户装了对讲机,却发现只能拨外线号码。

二、揭开Docker网络模型的"底裤"

Docker默认创建三种网络模式:

  1. bridge:默认的虚拟交换机(就像小区内部道路)
  2. host:直接使用宿主机网络(相当于住在大街上)
  3. none:彻底断网(闭关修炼模式)

重点说说这个bridge网络。它实际上做了三件事:

  • 创建虚拟网桥docker0(默认IP:172.17.0.1)
  • 给每个容器分配veth pair虚拟网卡
  • 通过iptables做NAT转发

用命令查看当前网络配置:

# 技术栈:Linux + Docker
brctl show docker0  # 查看网桥信息
iptables -t nat -L  # 查看NAT规则

三、实战:打造可互访的容器网络

方案1:使用自定义bridge网络

# 创建自定义网络(带DNS解析功能)
docker network create --driver bridge my_net

# 将容器接入自定义网络
docker run -d --name nginx3 --network my_net nginx:alpine
docker run -d --name nginx4 --network my_net nginx:alpine

# 现在可以互相ping通了!
docker exec -it nginx3 ping nginx4  # 成功返回ICMP响应

这就像给小区升级了智能门禁系统,业主可以直接按房号呼叫邻居。

方案2:直接指定容器IP

# 创建带固定子网的网络
docker network create --subnet=10.5.0.0/16 static_net

# 启动时指定IP(适合固定IP场景)
docker run -d --name redis \
  --network static_net \
  --ip 10.5.0.100 \
  redis:6

注意:过度使用静态IP会导致"IP地址管理噩梦",就像用纸质通讯录记电话号码。

四、那些年我们踩过的网络"神坑"

坑1:端口冲突引发"血案"

# 错误示范:两个容器映射相同主机端口
docker run -d --name web1 -p 8080:80 nginx
docker run -d --name web2 -p 8080:80 nginx  # 第二个会启动失败!

坑2:DNS解析突然抽风

# 技术栈:Dockerfile
FROM alpine
RUN echo "nameserver 8.8.8.8" > /etc/resolv.conf  # 硬编码DNS可能失效!

更推荐的做法:

docker run --dns 8.8.8.8 --dns-search example.com ...

坑3:防火墙拦路打劫

某次我在CentOS宿主机上死活连不上容器端口,最后发现是firewalld在搞鬼:

# 解决方案(二选一):
sudo firewall-cmd --add-port=8080/tcp --permanent  # 放行端口
# 或者
sudo firewall-cmd --zone=trusted --add-interface=docker0 --permanent

五、高阶玩家必备网络诊断术

神器1:nsenter进入容器网络命名空间

# 查看容器进程ID
docker inspect --format '{{.State.Pid}}' nginx1

# 进入容器的网络栈
nsenter -t <PID> -n ip addr  # 直接查看容器内网卡信息

神器2:tcpdump抓包分析

# 在宿主机上抓取docker0网卡流量
tcpdump -i docker0 -nn -v  # 看到底层的ARP、ICMP等协议交互

六、不同场景下的网络方案选型

场景 推荐方案 相当于现实中的...
开发环境单机多容器 自定义bridge网络 小区内部电话系统
微服务集群 使用overlay网络 跨城市分公司VPN
高性能网络需求 host网络模式 直接住临街商铺
安全隔离要求高 macvlan网络 给每个住户独立光纤入户

七、终极解决方案:上Kubernetes?

当容器数量超过50个时,建议考虑Kubernetes的CNI插件:

# 技术栈:Kubernetes网络策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-access
spec:
  podSelector:
    matchLabels:
      role: db
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: api
    ports:
    - protocol: TCP
      port: 5432  # 只允许api服务访问数据库端口

这就像给小区每个单元加装了人脸识别门禁,精确控制谁能进谁不能进。

八、写在最后:网络调优的哲学

  1. 不要迷信默认配置:Docker默认网络适合玩具级应用
  2. 基础设施即代码:所有网络配置应该版本化管理
  3. 监控比预防更重要:建议部署cAdvisor+Prometheus监控网络指标

记住,好的容器网络应该像优秀的城市交通系统——当你感觉不到它的存在时,才是它工作得最好的时候。