1. Docker容器网络基础概念在开始配置Docker容器网络之前我们需要先理解几个核心概念。Docker的网络模型与传统的物理网络有很大不同它通过虚拟化技术为容器提供了隔离的网络环境。Docker默认提供了五种网络驱动模式bridge默认网络模式为每个容器分配独立的网络命名空间host容器直接使用宿主机的网络栈overlay用于跨主机的容器通信macvlan为容器分配MAC地址使其在物理网络中显示为真实设备none禁用所有网络功能提示大多数情况下bridge模式已经能满足开发需求但在生产环境中可能需要考虑overlay或macvlan模式。我经常看到新手会混淆容器IP和宿主机IP的概念。实际上在bridge模式下每个容器都会获得一个私有IP通常是172.17.0.0/16网段这个IP只在宿主机内部可见。要让外部访问容器服务需要通过端口映射来实现。2. 默认bridge网络配置详解当安装Docker后它会自动创建一个名为bridge的默认网络。我们可以通过以下命令查看现有网络docker network ls输出结果通常类似这样NETWORK ID NAME DRIVER SCOPE a1b2c3d4e5f6 bridge bridge local这个默认bridge网络有几个重要特性容器间通过IP地址通信需要显式暴露端口才能从宿主机外部访问容器名称不能作为主机名解析我建议在开发环境中可以这样使用默认bridge网络docker run -d --name web -p 8080:80 nginx docker run -d --name db -e MYSQL_ROOT_PASSWORD123456 mysql:5.7这里我们启动了两个容器web和db。通过-p参数将web容器的80端口映射到宿主机的8080端口这样就能通过宿主机IP:8080访问nginx服务了。3. 创建自定义bridge网络虽然默认bridge网络能用但在实际项目中我强烈建议创建自定义bridge网络。这能带来几个好处容器间可以通过名称自动发现更好的隔离性可以自定义子网和网关创建自定义网络的命令很简单docker network create --driver bridge my_network创建时可以指定更多参数docker network create \ --driver bridge \ --subnet192.168.100.0/24 \ --gateway192.168.100.1 \ my_custom_network创建好网络后启动容器时指定网络docker run -d --name web --network my_network nginx docker run -d --name db --network my_network mysql现在web容器可以直接通过db这个主机名访问数据库容器而不需要知道它的IP地址。这种自动服务发现机制在微服务架构中特别有用。4. 容器网络连通性实战在实际项目中我们经常需要处理各种网络连接场景。下面我分享几个常见情况的处理方式。4.1 容器访问宿主机服务假设宿主机上运行着MySQL服务3306端口容器内需要连接这个服务。由于容器有独立的网络命名空间直接使用localhost或127.0.0.1是行不通的。解决方案是使用宿主机的特殊DNS名称host.docker.internalMac/Windows或宿主机真实IPLinux。例如# 在Linux上需要先获取宿主机IP HOST_IP$(ip route | grep default | awk {print $3}) docker run -it --rm mysql mysql -h $HOST_IP -u root -p4.2 容器间网络隔离有时我们需要限制某些容器间的通信。可以通过创建独立的网络来实现# 创建前端和后端两个网络 docker network create frontend docker network create backend # 前端服务连接到frontend网络 docker run -d --name frontend --network frontend nginx # 后端服务连接到backend网络 docker run -d --name backend --network backend node:14这样frontend和backend容器就无法直接通信了。如果需要连通可以使用docker network connect backend frontend4.3 跨主机容器通信在生产环境中容器经常需要跨主机通信。这时可以使用overlay网络# 在Swarm模式下创建overlay网络 docker swarm init docker network create --driver overlay my_overlay然后在不同主机上启动的容器只要使用同一个overlay网络就能直接通信。5. 网络问题排查与调试即使配置正确网络问题仍然经常发生。下面分享我常用的排查工具和技巧。5.1 基本诊断命令# 查看容器IP地址 docker inspect -f {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}} container_name # 进入容器测试网络连通性 docker exec -it container_name ping google.com # 查看容器网络配置 docker exec -it container_name ip addr5.2 常见问题及解决方案问题1端口绑定冲突错误信息Bind for 0.0.0.0:8080 failed: port is already allocated解决方案# 查找占用端口的进程 sudo lsof -i :8080 # 或者停止占用该端口的容器 docker stop $(docker ps -q --filter publish8080)问题2DNS解析失败容器内无法解析域名通常是DNS配置问题。解决方案# 启动容器时指定DNS服务器 docker run --dns 8.8.8.8 --dns 8.8.4.4 -it alpine ping google.com问题3网络驱动加载失败错误信息failed to setup IP tables: Unable to enable SKIP DNAT rule解决方案# 重启docker服务 sudo systemctl restart docker # 检查iptables规则 sudo iptables -L -n6. 高级网络配置技巧在长期使用Docker的过程中我积累了一些高级网络配置技巧能解决很多实际问题。6.1 网络别名Network Alias当容器需要多个名称解析时可以使用网络别名docker network create mynet docker run -d --name web --network mynet --network-alias website nginx docker run -d --name web2 --network mynet --network-alias website nginx现在其他容器可以通过website访问请求会在web和web2之间负载均衡。6.2 静态IP分配虽然不推荐但在某些特殊场景下可能需要为容器分配静态IPdocker network create --subnet10.0.0.0/24 my_static_net docker run -d --name static_container --network my_static_net --ip 10.0.0.100 nginx6.3 IPv6支持启用IPv6需要修改Docker守护进程配置# 编辑/etc/docker/daemon.json { ipv6: true, fixed-cidr-v6: 2001:db8:1::/64 } # 重启docker sudo systemctl restart docker # 创建IPv6网络 docker network create --ipv6 --subnet2001:db8:1::/64 ipv6_net7. 安全最佳实践容器网络配置不当会带来安全隐患。以下是我总结的安全建议限制容器网络能力docker run --cap-drop NET_RAW -d nginx使用用户定义的bridge网络替代默认bridge网络提供更好的隔离性。避免使用--nethost这会消除网络命名空间隔离。限制容器间通信docker network create --internal isolated_net定期审计网络配置# 查看所有端口映射 docker ps --format table {{.Names}}\t{{.Ports}} # 检查异常网络连接 docker run --rm -it --net container:web nicolaka/netshoot netstat -tulnp在实际项目中我通常会为不同安全级别的服务创建独立的网络并通过防火墙规则严格控制流量走向。比如数据库网络只允许特定应用服务器访问管理网络只允许运维人员访问等。