【Docker】容器网络探索(一):实战理解 Bridge 网络
本专栏文章持续更新,新增内容使用蓝色表示。
环境介绍
开始之前,先介绍一下我的环境:
-
Kubernetes 集群(1 master + 2 worker)
-
Calico 网络插件
-
Docker 容器运行时
如果只是想了解 Docker 网络,只需安装 Docker 即可,无需搭建完整的 K8s 集群。
一、初始环境检查
1.1 查看初始网络状态
在安装 Docker 之前,建议先使用以下命令查看主机的网络接口情况,和后续进行对比。正常情况下,应该只能看到 lo、ens33 等基础网络接口。
ip a s
1.2 安装 Docker 后检查网络
安装 Docker 之后,再次运行 ip a s 命令,会出现一个新的网络接口(docker0 网桥)。

后续命令如果权限不够,可以加 sudo 提权,此处为了演示方便,直接切换到了 root 用户身份。
1.3 查看 Docker 网络列表
使用 docker network ls 命令列出 docker 当前网络:
# 需要 sudo 提权
docker network ls

从上图的输出结果中可以看到有三种不同的驱动,分别为 bridge、host、null。
安装 docker 之后这三种驱动就会创建出三个不同类型的网络。其中 bridge 是默认网络,创建容器时如果没有明确指定,都会自动加入这个网络。
二、 默认 Bridge 网络
使用 docker network inspect bridge 命令查看该网络的详细信息:
docker network inspect bridge

重点关注:Subnet 网段、Gateway 网关、Containers 列表(当前为空)。
2.1 创建测试容器
终端 1 - 创建并进入容器:
docker run -it --name apline0 --rm alpine sh
终端 2 - 观察网络变化:
# 查看新出现的 veth 接口
ip a s
# 再次检查 bridge 网络
docker network inspect bridge
使用 ip a s 命令查看网络接口信息时,可以发现多了一个 veth55d60a2@if3(名字可能不同)。
并且查看 bridge 网络信息,发现 Containers 属性里面多了 apline0 容器的信息。

2.2 分析网络接口对应关系
下面针对多出来的接口进行分析。
终端 2 - 在宿主机查看 veth 接口详情
ip -json address show dev veth55d60a2 | jq .
# 如果未安装 jq,可以使用以下命令。
# CentOS/RHEL
dnf install jq
# Ubuntu/Debian
apt install jq

终端 1 - 在容器内部使用 ip a s 命令查看网络接口情况:
ip a s

注意:在我的环境中,由于使用了 Calico 网络插件的 IPIP 模式,会看到 tunl0@NONE 接口。如果只安装了 Docker,应该只会看到 lo 和 eth0 两个接口。
现在再来解释一下,@if 后面的数字含义:
宿主机视角 (Host) 容器视角 (Container)
───────────────────────────────────────────────────
10: veth55d60a2@if3 3: eth0@if10
↑ ↑
在宿主机是第10个接口 在容器内是第3个接口
对端是容器的第3个接口 对端是宿主机的第10个接口
这是一对 veth pair,就像"虚拟网线"的两端。

2.3 网络连通性测试
2.3.1 容器访问外部网络
终端 1 - 在 alpine0 容器内测试:
ping -c 2 baidu.com
在 bridge 网络模式下,容器可以访问外部网络。

2.3.2 宿主机与容器通信
终端 2 - 在宿主机测试:
ping -c 3 172.17.0.2 # 替换为 alpine0 的实际 IP
宿主机也可以直接 ping 通容器。
2.3.3 容器间通信测试
终端 3 - 创建第二个容器:
docker run -it --name apline1 --rm alpine sh
顺便验证一下@ifx的对应关系:


在 alpine1 容器内测试:
ping -c 2 172.17.0.2

既然 IP 可以 ping 通,那域名呢?
![]()
答案是不能,因为默认的 bridge 网络不支持容器间的自动 DNS 解析,这是它的主要限制之一。不过自定义的 bridge 模式支持域名解析。(第三部分介绍相关内容)
2.4 端口映射与外部访问
既然容器可以 ping 通外部网络,那外部网络能否 ping 通容器呢?
答案是需要通过端口映射。
创建一个名为 nginx-expose 的容器,将宿主机的 8080 端口和容器的 80 端口进行关联。
docker run -d --name nginx-expose --rm -p 8080:80 nginx
docker network inspect bridge | grep nginx-expose -C 5

此时 curl 宿主机的 8080 端口就可以看到 nginx 的欢迎页面。

在浏览器输入http://192.168.30.130:8080,也可以看到欢迎页面。

三、自定义 Bridge 网络
解决默认 bridge 网络的限制。
3.1 创建自定义网络
docker network create -d bridge mynet
docker network ls
![]()

使用以下命令查看自定义网络带来的变化:
ip a s

docker network inspect mynet

3.2 在自定义网络中测试
在自定义的 mynet 网络中创建两个容器,进行测试。
# 终端1
docker run -it --name alpine-mynet0 --hostname alpine-mynet0 --network mynet --rm alpine sh
# 终端2
docker run -it --name alpine-mynet1 --hostname alpine-mynet1 --network mynet --rm alpine sh


此处主要测试域名能否 ping 通:

答案是可以。
即使不指定主机名,也能通过容器名进行通信:
# 终端3
docker run -it --name alpine-mynet2 --network mynet --rm alpine sh


其余网络模式在下一篇介绍。
如有问题或建议,欢迎在评论区中留言~
更多推荐
所有评论(0)