Docker的网络
本文最后更新于 2024年12月31日
Docker的网络用于容器间的互联和通信,以及宿主机端口映射,容器IP变动的时候可以设置网络直接使用服务名进行网络通信而不受影响。类似于虚拟机软件分配IP地址给各个安装的虚拟机以及物理机,虚拟机之间以及虚拟机和物理机之间可以相互通信。
1.查看容器的网络
1.查看容器网络类型
docker inspect命令查看关于Networks的部分
docker inspect 容器ID当前容器是bridge网络,网关是172.17.0.1, IP是172.17.0.2
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "2def63006d0705d822ebd7269baf1512be0fc886c40e9047f35635ef21585b33",
"EndpointID": "4fd79243a84032b34a57a39b0ffc03136bef175498980abdc097117e17f135fe",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
2.查看当前有多少个docker网络
docker network ls[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
2def63006d07 bridge bridge local
f8b834999d26 host host local
fd9dc003ef95 lzjnet bridge local
2ca13d3f5552 none null local3.查看网络的情况
docker network inspect 网络名网络lzjnet的网络类型是bridge,还有IP等信息
[
{
"Name": "lzjnet",
"Id": "fd9dc003ef956e7b3f01d74b81f5fc6cc04c76ce5144beadc9707dd4a7a41134",
"Created": "2024-11-26T23:12:55.276879774+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
2.Docker的网络类型
几种常见的网络类型
| 网络模式 | 简介 |
|---|---|
bridge |
默认为该模式,为每一个容器分配和设置IP,并将容器连接到默认的虚拟网桥docker0 |
host |
容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口 |
none |
容器有独立的network namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,IP等 |
container |
新创建的容器不会自动创建自己的网卡和配置IP,而是和一个指定的容器共享IP和端口范围等 |
2.1 bridge网络
1.主机和容器联网
Docker服务默认会创建一个网桥(上有一个docker0的内部接口),该桥接网络的名称为docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信。
2.容器之间联网
Docker启动一个容器时会根据docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关,因为在同一宿主机内的容器都接入同一网桥,这样容器之间就可以通过容器的Container-IP直接通信。
3.bridge网络的分配机制

docker run的时候,没有指定network的话,默认使用的网桥模式就是bridge(docker0)。在宿主机ifconfig就可以看见docker0和自己创建的网络(eth0, eth1…..),lo代表127.0.0.1。
网桥docker0创建一对对等的虚拟设备接口,一个叫veth,另一个叫eth0,成对匹配。
整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair)
每个容器内部也有一块网卡,每个接口叫eth0,docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。
验证veth-pair:
查看正在运行的Docker容器
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38188376416b tomcat "catalina.sh run" About a minute ago Up About a minute 8080/tcp inspiring_austin宿主机执行ip addr查看宿主机的网络情况
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:44:65:de brd ff:ff:ff:ff:ff:ff
inet 192.168.228.104/24 brd 192.168.228.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::2ac6:ec4:9411:4da8/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ff:ca:bc:ec brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:ffff:feca:bcec/64 scope link
valid_lft forever preferred_lft forever
15: vethc5f3f03@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 26:9a:2e:de:95:5a brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::249a:2eff:fede:955a/64 scope link
valid_lft forever preferred_lft forever
进入容器,一般需要先更新tomcat容器的yum,再安装工具iproute2
sudo apt-get update
sudo apt-get upgrade
apt-get install -y iproute2然后,在容器内执行ip addr查看容器的网络情况
root@38188376416b:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> 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
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
然后可见宿主机的网卡 15: vethc5f3f03@if14 和容器网卡 14: eth0@if15两两匹配,互互相同
2.2 host网络
直接使用宿主机的IP地址与外界通信,不需要额外进行NAT转换。
容器将不再获得一个独立的网络名称空间,而是和宿主机共用一个网络名称空间,容器将不会虚拟出自己的网卡,而是使用宿主机的IP和端口,容器没有自己的IP。
这种模式下,使用-p端口映射是无效的,也是没有任何意义的。

2.3 none网络
等同于禁用网络功能,不为容器进行任何网络配置,容器没有网卡,路由等信息,只有一个本地回环网卡lo
2.4 container网络
新建的容器和一个已经存在的容器共享一个网络IP配置而不是和宿主机共享,新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP,端口范围等,同样,两个容器除了网络方面,其他的例如文件系统,进程列表等还是隔离的。

需要注意的是:
1.继承和被继承的容器的容器内端口不能是相同的,否则会导致冲突,因为两个容器共享网段和IP
验证:先启动一个tomcat容器tomcat86,该容器内的程序会占用容器的8080,在启动另一个tomcat容器tomcat87和前者共享网络,因为也是基于tomcat镜像,所以同样会占用容器的8080,两个容器端口范围是共享的,导致报错Error response from daemon: conflicting options: port publishing and the container type network mode.
docker run -d --privileged=true -p 8086:8080 --name tomcat86 tomcat
docker run -d --privileged=true -p 8086:8080 --network container:tomcat86 --name tomcat87 tomcat[root@localhost ~]# docker run -d --privileged=true -p 8086:8080 --name tomcat86 tomcat
c8464b5448296b51bc5b4e4598acce709513aa6ac7fac6ef335e5a39e8a785f3
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c8464b544829 tomcat "catalina.sh run" 4 seconds ago Up 2 seconds 0.0.0.0:8086->8080/tcp tomcat86
0bad9102a5a7 alpine "/bin/sh" 11 minutes ago Up 11 minutes alpine1
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# docker run -d --privileged=true -p 8086:8080 --network container:tomcat86 --name tomcat87 tomcat
docker: Error response from daemon: conflicting options: port publishing and the container type network mode.
See 'docker run --help'.
2.被继承的容器结束运行后,继承它的容器也会失去网络功能,只剩下一个回环网卡lo
验证:先运行一个精简版Linux容器alpine1,在运行一个同样的容器alpine2,指定和alpine1共享网络,查看容器内网络可见网卡名称和IP地址都是完全一样的
docker run -it --name alpine1 alpine /bin/sh[root@localhost ~]# docker run -it --name alpine1 alpine /bin/sh
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
docker run -it --name alpine2 --network container:alpine1 alpine /bin/sh[root@localhost ~]# docker run -it --name alpine2 --network container:alpine1 alpine /bin/sh
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
关闭容器alpine1,进入容器alpine2查看IP,发现eth网卡跟着消失了,只剩下lo
[root@localhost ~]# docker stop alpine1
alpine1
[root@localhost ~]# docker exec -it alpine2 /bin/sh
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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 forever2.5 自定义网络
为什么要自定义网络?
1.容器间的互联和通信以及端口映射
2.bridge模式网络分配给容器的IP是可能随着容器的启动关闭而导致分配的地址发生变动的,但是Docker自带的bridge网络比较简单,没有内置DNS功能,自定义网络后,容器IP变动的时候可以通过服务名直连网络而不受影响,当用户创建自定义网络时,Docker自动配置了一个内置DNS服务器,这个DNS服务器会根据容器的名称自动解析对应的IP地址。
自定义网络默认也是采用桥接模式bridge,只是功能比默认的那个更强,自然就维护好了容器名和IP的映射关系(DNS)
验证:
创建一个网络lzjnet
docker network create lzjnet创建容器tomcat1 tomcat2,指定我们自己创建的网络,然后互PING
docker run -it --privileged=true --network lzjnet --name alpine81 alpine
docker run -it --privileged=true --network lzjnet --name alpine82 alpine[root@localhost ~]# docker attach alpine81
/ # ping alpine82
PING alpine82 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.889 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.195 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.181 ms
64 bytes from 172.18.0.3: seq=3 ttl=64 time=0.167 ms
64 bytes from 172.18.0.3: seq=4 ttl=64 time=0.547 ms
^C
--- alpine82 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.167/0.395/0.889 ms[root@localhost ~]# docker attach alpine82
/ # ping alpine81
PING alpine81 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.079 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.133 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.169 ms
64 bytes from 172.18.0.2: seq=3 ttl=64 time=0.186 ms
64 bytes from 172.18.0.2: seq=4 ttl=64 time=0.663 ms
64 bytes from 172.18.0.2: seq=5 ttl=64 time=0.260 ms
64 bytes from 172.18.0.2: seq=6 ttl=64 time=0.176 ms
^C
--- alpine81 ping statistics ---
7 packets transmitted, 7 packets received, 0% packet loss
round-trip min/avg/max = 0.079/0.238/0.663 ms可以发现可以使用容器名相互PING通
3.总结
Docker可以使用4种网络模式来实现容器之间以及和宿主机的网络通信,自己实现自定义的网络桥接模式功能更强。
"如果文章对您有帮助,可以请作者喝杯咖啡吗?"
微信支付
支付宝