一、Docker网络那些事儿

刚开始用Docker的时候,总觉得容器之间通信特别玄学——明明在本地跑得好好的服务,一放进容器就互相找不着北。后来才发现,这锅得Docker的默认网络设置来背。今天咱们就来聊聊怎么优化这个默认配置,让容器们愉快地聊天。

Docker安装后会默认创建三种网络:bridge(默认)、hostnone。大多数情况下,你的容器都跑在bridge网络上,但这个默认桥接网络有个致命伤:容器间只能用IP地址通信,而且每次重启容器IP都可能变。想象一下,你每次叫同事都得先问他今天坐哪个工位,这谁受得了?

# 查看Docker现有网络(技术栈:Docker CLI)
docker network ls
# 输出示例:
# NETWORK ID     NAME      DRIVER    SCOPE
# a1b2c3d4e5f6   bridge    bridge    local
# d7e8f9g0h1i2   host      host      local
# j3k4l5m6n7o8   none      null      local

二、手动创建自定义桥接网络

解决上述问题最直接的办法就是自定义桥接网络。和默认桥接网络不同,自定义网络中的容器既可以用IP通信,也能直接用容器名互相访问。下面我们动手创建一个:

# 创建名为my_net的自定义网络(技术栈:Docker CLI)
docker network create --driver bridge my_net

# 运行两个容器并加入该网络
docker run -d --name web --network my_net nginx
docker run -d --name db --network my_net redis

# 进入web容器测试能否ping通db
docker exec -it web ping db
# 成功输出表示容器间通过主机名通信正常

关键优势

  1. DNS自动解析:容器名直接当域名用
  2. 隔离性:不同项目的容器可以用不同网络
  3. 稳定性:容器重启后IP可能变化,但名字始终有效

三、高级网络参数调优

对于生产环境,我们还需要关注这些参数:

# 创建带高级配置的网络(技术栈:Docker CLI)
docker network create \
  --subnet=172.20.0.0/16 \       # 指定子网范围
  --gateway=172.20.0.1 \         # 设置网关
  --opt "com.docker.network.bridge.name"="mybridge" \ # 自定义网桥名
  my_advanced_net

# 验证网络配置
docker network inspect my_advanced_net
# 输出中会显示详细的IPAM配置和选项

注意事项

  • 子网不要和宿主机或其他网络冲突
  • 对延迟敏感的应用可以添加--internal禁止外网访问
  • 大数据量传输时考虑调整MTU(默认1500可能不适合云环境)

四、容器通信的典型问题解决方案

场景1:跨主机容器互联

当容器分布在多台宿主机时,默认的桥接网络就不够用了。这时候可以用Overlay网络(需要Swarm模式):

# 初始化Swarm集群(技术栈:Docker Swarm)
docker swarm init

# 创建跨主机的Overlay网络
docker network create --driver overlay --attachable my_overlay

# 在不同主机运行的容器都能加入此网络
docker service create --network my_overlay --name demo nginx

场景2:容器访问宿主机服务

当容器需要访问宿主机上的MySQL等服务时,直接用localhost会指向容器自己。这时候有两种方案:

# 方案1:使用host.docker.internal(Mac/Windows版Docker默认支持)
ping host.docker.internal

# 方案2:启动时添加--add-host参数(Linux通用方案)
docker run --add-host host.docker.internal:host-gateway your_image

五、安全加固与监控

网络通了之后,别忘了安全问题:

# 限制容器网络权限(技术栈:Docker安全)
docker run \
  --network my_net \
  --cap-drop NET_RAW \      # 禁止RAW套接字
  --read-only \             # 只读文件系统
  nginx

# 查看容器网络流量
docker stats --format "table {{.Name}}\t{{.NetIO}}"

推荐的安全实践:

  1. 非必要不暴露端口(避免使用-p 80:80
  2. 为每个微服务创建独立网络
  3. 定期检查iptables规则(Docker会动态修改)

六、实战案例:微服务网络规划

假设我们有一个电商系统,包含以下服务:

  • 前端(Vue.js)
  • 订单服务(Spring Boot)
  • 支付服务(Go)
  • MySQL数据库
  • Redis缓存

合理的网络架构应该是:

# 创建业务网络
docker network create --driver bridge ecommerce

# 启动数据库服务(隔离在后端子网)
docker run -d --name mysql --network ecommerce -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

# 启动应用服务(可互相通信但隔离数据库)
docker run -d --name order-service --network ecommerce -p 8080:8080 spring-boot-app
docker run -d --name payment-service --network ecommerce -p 8081:8081 go-app

七、总结与建议

经过这些优化,你的Docker网络应该已经告别了"失联"状态。最后给三个黄金建议:

  1. 永远不要用默认的bridge网络,就像不要用root用户跑应用一样
  2. 网络划分要遵循最小权限原则
  3. 复杂环境考虑上Kubernetes的CNI插件

记住,好的网络设计应该是:让该通的流量畅通无阻,不该通的流量寸步难行。