Docker从默认网络到自定义网络实现方式
作者:六月五日
引言:容器通信的 “隐形障碍”—— 为什么默认网络不够用?
当你使用Docker启动了MySQL容器和Java应用容器,让Java应用通过MySQL的IP地址连接数据库,一切看似顺利。然而,一旦重启MySQL容器,IP地址发生变化,Java应用就会直接报错“连接不上数据库”。这就是Docker默认网络给我们带来的困扰。
本文将深入解析Docker网络机制,从默认bridge模式存在的问题,到自定义网络的解决方案,教会你如何让容器之间能够“用名字说话”,彻底摆脱IP变动带来的麻烦。适合有一定容器操作基础的Docker用户,以及需要部署多容器应用(如前端 + 后端 + 数据库)的开发者阅读。
Docker 默认网络:bridge 模式的 “利与弊”
虚拟网桥 docker0
Docker安装后会自动创建一个名为docker0的虚拟网卡,它就好比一个“虚拟交换机”。其默认IP段为172.17.0.0/16,这意味着前16位是固定的,后16位可供分配,范围从172.17.0.1到172.17.255.254。
我们可以通过执行ip addr命令来验证,在输出结果中能看到名为docker0的网卡及其IP地址,比如172.17.0.1 。
IP分配机制
所有容器在启动时默认会连接到docker0网桥,并自动分配IP地址。
第一个容器通常会被分配到172.17.0.2,第二个则是172.17.0.3,依此类推。由于这些容器都连接到docker0网桥,处于同一网段,所以它们可以通过IP直接进行通信,例如使用ping 172.17.0.2命令。
痛点:IP 变动导致的 “连接失效” 问题
虽然默认的bridge模式能让容器间实现基本通信,但它存在一个致命的缺点,即容器的IP地址是动态分配的。当容器重启、删除重建后,IP地址很可能发生变化。
比如MySQL容器重启后,IP地址可能从172.17.0.2变成172.17.0.4 。
对于依赖IP地址进行连接的应用,如Java应用连接数据库,这种IP变动会导致连接失效,并且需要手动修改配置,操作起来极其繁琐。
Docker 网络操作命令:从创建到管理
核心命令
- 创建自定义网络:使用docker network create [网络名]命令可以创建一个独立的虚拟网络,帮助我们避免默认网络的IP变动问题。例如,执行docker network create itheima就能创建一个名为itheima的网络。
- 查看所有网络:docker network ls命令会以列表形式显示系统中的所有网络,包括默认的bridge、host、none网络,以及我们自定义创建的网络,如itheima 。
- 连接容器到网络:通过docker network connect [网络名] [容器名],可以让已运行的容器加入指定网络,并且容器能够同时属于多个网络。比如执行docker network connect itheima mysql,就能将mysql容器加入到itheima网络。
- 查看网络详情:docker network inspect [网络名]命令可以获取网络的详细信息,包括IP段、连接的容器等。以docker network inspect itheima为例,通过该命令我们能查看容器在itheima网络中的IP等配置。
辅助命令
- 删除网络:docker network rm [网络名]用于删除指定的网络,但需要先断开所有容器与该网络的连接。
- 清理未使用网络:docker network prune命令会删除没有容器使用的网络,从而释放系统资源。
- 断开连接:使用docker network disconnect [网络名] [容器名],可以断开容器与指定网络的连接。
命令记忆法
所有关于Docker网络的操作命令都以docker network开头,这样记忆起来更加方便,你可以简单理解为“网络操作 = docker network + 具体动作(create/ls/rm等)”。
实战:用自定义网络解决容器通信难题
步骤1:创建自定义网络
执行docker network create itheima命令创建名为itheima的网络,然后通过docker network ls确认网络已成功创建。
自定义网络有个特点,它会自动选择未被占用的IP段。
比如默认bridge网络使用了172.17.x.x网段,自定义网络可能就会使用172.18.x.x网段。
步骤2:将容器加入自定义网络
- 方式一:创建容器时指定网络(推荐)
启动MySQL容器时,直接使用–network itheima参数将其加入itheima网络,命令如下:
docker run -d --name mysql --network itheima -e MYSQL_ROOT_PASSWORD=123 mysql:8
同样,启动Java应用容器时也加入itheima网络:
docker run -d --name myapp --network itheima -p 8080:8080 app:1.0
- 方式二:给已运行的容器动态加入网络
假设mysql容器已经在默认网络中运行,我们可以使用以下命令将其动态加入itheima网络:
docker network connect itheima mysql
通过这种方式,mysql容器会同时属于默认bridge和itheima网络,也就会拥有两个IP地址。
步骤3:验证 “容器名通信”
首先通过docker exec -it myapp bash进入myapp容器,然后在容器内使用ping mysql命令测试与MySQL容器的连接。
结果是能成功ping通,这是因为Docker会自动将mysql解析为其在itheima网络中的IP地址,比如172.18.0.2 。而且即使mysql容器重启,IP地址发生变化,ping mysql命令依然有效,因为Docker的DNS会更新解析。
自定义网络的核心优势与原理
内置DNS
在自定义网络中,Docker自带了DNS服务,它会将容器名映射为该网络内的IP地址。
这使得容器之间可以直接使用容器名进行通信,无需记住复杂的IP地址。而默认的bridge网络并没有这个功能,在bridge网络中容器通信必须使用IP地址,或者手动配置hosts文件。
多网络支持
一个容器可以同时加入多个网络,比如同时处于默认bridge和自定义itheima网络。
我们可以通过docker inspect myapp命令,在输出结果的Networks字段中查看容器所属所有网络的配置信息,每个网络都会为容器分配独立的IP地址。
这种多网络支持不仅增加了容器通信的灵活性,还提升了网络的隔离性,不同自定义网络之间默认是隔离的,只有加入同一网络的容器才能相互通信,安全性更高。
对比默认bridge
与默认的bridge网络相比,自定义网络解决了IP变动的问题,容器之间通过容器名通信更加稳定。默认bridge网络依赖动态变化的IP地址,一旦IP改变就会导致通信故障,而自定义网络通过内置DNS实现容器名到IP的动态解析,即使IP变化也不影响通信。
避坑指南:网络配置常见错误与解决
容器加入网络后仍无法通信?
- 检查是否在同一网络:使用docker network inspect 网络名命令,确认两个需要通信的容器都在该网络的容器列表中。
- 检查防火墙:宿主机的防火墙可能会阻止容器间的通信,可以临时关闭防火墙进行测试,命令为systemctl stop firewalld 。
- 检查应用端口:确认容器内应用是否监听了正确的端口,比如MySQL默认端口是3306,需要检查其配置中是否开放了该端口。
自定义网络IP段冲突怎么办?
如果担心自定义网络IP段冲突,可以在创建网络时手动指定IP段,例如:
docker network create --subnet 192.168.100.0/24 mynet
如何查看容器的所有网络IP?
使用以下命令可以查看容器的所有网络IP:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}} {{end}}' 容器名
总结:容器网络的 “最佳实践”
对于多容器应用,使用自定义网络是必不可少的,它能有效避免IP变动带来的问题。在创建容器时,优先使用–network参数指定网络,这样比动态加入网络更加规范和可靠。
当遇到网络配置问题时,docker network inspect命令是排查问题的有力工具。另外,定期使用docker network prune命令清理无用网络,有助于释放系统资源。
简而言之,自定义网络实现了容器通信从“记IP”到“叫名字”的转变,是Docker多容器部署中必须掌握的技能。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
