Docker:网络

Docker:网络

理解Docker 0

测试环节

清空全环境

1
2
3
4
$ ip addr
lo: inet 127.0.0.1 # 本机环回地址
eth0: inet 114.51.41.191 # 阿里云内网地址
docker0: inet 172.16.0.1 # Docker内网地址

三个网络

Docker 如何处理容器的网络访问的

我们随便创个容器,然后康康里面的网络

1
2
3
4
5
6
7
8
9
10
11
12
docker run -d -P --name tomcat01 tomcat
docker exec -it tomcat01 ip addr
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0@if104: mtu 1500 qdisc noqueue state UP group default
link/ether e2:1e:66:14:2a:3b brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.16.0.2/24 brd 172.16.0.255 scope global eth0
valid_lft forever preferred_lft forever

这里如果提示找不到命令之类的很正常,是因为官方下载的精简版啥都没有

1
2
3
4
# 换国内镜像源下载一下相关的东西
echo "deb http://mirrors.tuna.tsinghua.edu.cn/debian stable main" > /etc/apt/sources.list
apt update
apt install -y iproute2

试试能不能ping

1
2
3
4
5
root@iZf8z4m0zzs3eoirsd64fvZ:~# ping 172.16.0.2                               
PING 172.16.0.2 (172.16.0.2) 56(84) bytes of data.
64 bytes from 172.16.0.2: icmp_seq=1 ttl=64 time=0.046 ms
64 bytes from 172.16.0.2: icmp_seq=2 ttl=64 time=0.048 ms
64 bytes from 172.16.0.2: icmp_seq=3 ttl=64 time=0.046 ms

Linux 可以 ping 通容器
我们每启动一个docker容器,docker 就会给 docker 容器分配一个 ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是evth-pair

主机中Docker的内网地址172.16.0.1
容器中内网地址172.16.0.2

查看过容器之后,我们回到Linux,再次使用ip addr
发现多了一个

1
2
3
4
104: veth68a85b9@if2:  mtu 1500 qdisc noqueue master docker0 state UP group default                                 
link/ether 32:28:55:e1:23:68 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::c05d:c8ff:fe40:159d/64 scope link
valid_lft forever preferred_lft forever

我们和之前容器里的对比一下

1
2
3
4
2: eth0@if104:  mtu 1500 qdisc noqueue state UP group default                 
link/ether e2:1e:66:14:2a:3b brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.16.0.2/24 brd 172.16.0.255 scope global eth0
valid_lft forever preferred_lft forever

发现都是104,这两个很像啊(警撅

我们再启动一个测试一下

1
2
3
4
5
6
$ docker run -d -P --name tomcat02 tomcat
$ docker exec -it tomcat02 ip addr
2: eth0@if105: mtu 1500 qdisc noqueue state UP group default
link/ether 22:2f:74:cd:49:fd brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.16.0.3/24 brd 172.16.0.255 scope global eth0
valid_lft forever preferred_lft forever

我们回到主机也查看一下

1
2
3
4
5
$ ip addr
105: veth1fe5858@if2: mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether e6:ce:78:85:15:79 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::e4ce:78ff:fe85:1579/64 scope link
valid_lft forever preferred_lft forever

哦!容器内的网卡和Linux上的网卡总是同时出现,是一对的(我不反对这门亲事
这是 veth-pair 技术(虚拟以太网对)

veth pair 是什么?

veth(virtual ethernet device) 是一对成对的虚拟网卡,一端连着容器的网络命名空间,另一端连着宿主机或 bridge(桥接网络)

1
[容器 eth0] ←→ [veth-pair] ←→ [宿主机 vethXXX] ←→ [docker0 bridge]

veth pair是一对虚拟接口,>-----<可以当做一个桥梁,链接虚拟网络设备
OpenStac,Docker 容器之间的连接,ovs 的连接,都是使用veth pair
可恶啊,连网卡都是成对出现的😭

主机和容器能 ping 通,容器和容器可以吗?

我们逝逝用tomcat01pingtomcat02

1
2
3
4
$ docker exec -it tomcat01 ping 172.16.0.3
PING 172.16.0.3 (172.16.0.3) 56(84) bytes of data.
64 bytes from 172.16.0.3: icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from 172.16.0.3: icmp_seq=2 ttl=64 time=0.058 ms

可以!

小结

1
2
3
4
5
6
7
172.16.0.1 - Docker 0,安装就有,相当于一个路由器
172.16.0.2 - Tomcat01
172.16.0.3 - Tomcat02

172.16.0.2 - [2: eth0@if104] >-< [104: veth68a85b9@if2] - |----------|
|172.16.0.1|
172.16.0.3 - [2: eth0@if105] >-< [105: veth1fe5858@if2] - |----------|

结论:
tomcat01和tomcat02是公用的一个路由器,docker0。
所有的容器不指定网络的情况下,都是 docker0 路由的,docker 会给我们的容器分配一个默认的可用IP。
Docker中的所有的网络接口都是虚拟的,虚拟的转发效率高。
如果把容器删除,对应网桥也会自动被删除。

–link(弃用)

我们编写了一个微服务,database url = ip,项目不重启,但是换掉了ip,如何通过名字来访问容器,就像域名一样

自定义网络

查看所有的 Docker 网络

1
2
3
4
5
$ docker network ls                             
NETWORK ID NAME DRIVER SCOP
65ad4e5d1a43 bridge bridge local
6a0642ae8ae9 host host local
fc39f8592507 none null local

网络模式

bridge:桥接 Docker(默认,自己创建也使用该模式)
none:不配置
host:和宿主机共享网络
container:容器内网络连通(用得少,局限性大)

测试

清空容器

网络又恢复原状了

1
2
3
4
5
6
7
8
$ docker rm -f $(docker ps -aq)
$ ip addr
lo: inet 127.0.0.1 # 本机环回地址
eth0: inet 114.51.41.191 # 阿里云内网地址
docker0: inet 172.16.0.1 # Docker内网地址

# --net bridge是默认值,不加也会自动设为 bridge
$ docker run -d -P --name tomcat01 --net bridge tomcat
自定义一个网络
1
2
3
4
5
6
7
8
9
10
11
12
#我们可以自定义一个网络!
--driver bridge
--subnet 192.168.0.0/16 # 192.168.0.1 ~ 192.168.255.255
--gateway 192.168.0.1
# 创建一个网络
$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 查看网络
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
4f37c97635e1 mynet bridge local
$ docker network inspect mynet
...
subnet

声明 IP 地址范围

这是一个 CIDR 格式 的子网表示法

  • 192.168.0.0 是网络地址(起点)
  • /16 表示 子网掩码是 255.255.0.0,也就是前 16 位固定
  • 192.168.0.0 ~ 192.168.255.254(共 65534 个 IP)
gateway

“容器从这个网络访问外部网络的时候,默认要经过的那个 IP”。

通常就是 Docker 自动分配的第一号 IP 地址(比如你没写的话,它就会默认设为192.168.0.1

使用自定义网络
1
2
3
4
$ docker run -d -P --name tomcat-net-01 --net mynet tomcat
fa95dccba1c86e4d3ca0a5e5605dabf828e9cd90b59f7176f0f18e685fafd0e7
$ docker run -d -P --name tomcat-net-02 --net mynet tomcat
6ce874f753348ddbd20d8ed4d5d713029e1316e59804f7c0b28462e8833c163a
再次查看自定义网络
1
$ docker network inspect mynet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"Containers": {
"6ce874f753348ddbd20d8ed4d5d713029e1316e59804f7c0b28462e8833c163a":
{
"Name": "tomcat-net-02",
"EndpointID": "970adc2b31a5c20120712c95c812513431d87435802d4ed72781eed755affdae",
"MacAddress": "f6:0b:b1:87:9a:ff",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"fa95dccba1c86e4d3ca0a5e5605dabf828e9cd90b59f7176f0f18e685fafd0e7": {
"Name": "tomcat-net-01",
"EndpointID": "b30b5f497ce519e32e0b164e4db684c8f74eb8997f3b6803e1bb28c81dbca643",
"MacAddress": "52:5c:3c:8b:66:e4",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
...
容器间ping测试
1
2
3
4
5
$ docker exec -it tomcat-net-01 ping **tomcat**-net-02
PING tomcat-net-02 (192.168.0.3) 56(84)bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3):icmp_seq=1 ttl=64 time=0.055 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3):icmp_seq=2 ttl=64 time=0.063 ms
64 bytes from ttl=64 time=0.073 ms

我们发现自定义网络 Docker 会自动维护好对应的关系

自定义网络的好处

redis | mysql:不同的集群使用不同的网络,保证集群是安全和健康的

网络连通

背景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
172.16.0.1 - Docker 0
172.16.0.2 - Tomcat01
172.16.0.3 - Tomcat02

172.16.0.2 - [2: eth0@if104] >-< [104: veth68a85b9@if2] - |-Docker 0-|
|172.16.0.1|
172.16.0.3 - [2: eth0@if105] >-< [105: veth1fe5858@if2] - |-Docker 0-|

-----------------------------------------------------------------------------

192.168.0.1 - mynet
192.168.0.2 - tomcat-net-01
192.168.0.3 - tomcat-net-02

192.168.0.2 - tomcat-net-01 >-< - |---mynet---|
|192.168.0.1|
192.168.0.3 - tomcat-net-02 >-< - |---mynet---|
1
2
$ docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known

如上所示,tomcat-net-01和Tomcat01属于不同的网段,互不干扰,因此不能直接 ping 通
因此我们需要网络连通

操作

1
2
3
4
5
$ docker network --help                                            
...
Commands:
connect Connect a container to a network
# 把一个容器连接到一个网络上

目标:打通tomcat01 - mynet

1
2
$ docker network connect mynet tomcat01
$ docker network inspect mynet
1
2
3
4
5
6
7
8
9
10
11
"Containers": {
"1844c7d02186d8483facb4110ad19e141e8cdb7b31d2581357078bfe6ae16cb6":
{
"Name": "tomcat01",
"EndpointID": "58ccd4d9dc59d07b20982d65aa4899a2afdd...",
"MacAddress": "e6:78:90:20:f3:25",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
},
...
}

我们发现连通之后,tomcat01直接被加进了mynet
而且是拥有了新的 ip :192.168.0.4
一个容器,两个地址
很像阿里云服务里的公网 ip 和私网 ip
其实就是多加了块虚拟网卡
假设要跨网络操作别人,就需要使用docker network connect连通

实践:部署Redis集群

创建网卡

1
$ docker network create redis --subnet 172.38.0.0/16

忙,停更


Docker:网络
https://www.zheep.top/posts/4017790120/
作者
西行寺岩羊
发布于
2025年5月18日
许可协议