docker网络
1 docker网络类型
docker网络
Docker安装时会自动的在Docker host上创建三种网络,我们可以使用docker network ls查看。这三种网络分别是none网络、host网络、bridge网络,bridge网络是我们在创建容器时默认使用的网络。
[root@ws ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
38c3edc35477 bridge bridge local
ce68bd41327a harbor_harbor bridge local
4f77756645cb host host local
6fc2732f43cb none null local
docker网络-None网络
故名思议,none网络就是什么都没有的网络。在这个网络下的容器除了lo,没有其他任何网卡。容器创建时,可以通过--network=none指定使用none网络,通过下面这个示例可以看出,创建容器时指定容器网络类型为none时,容器内只有一个lo网络
[root@ws ~]# docker run -it --name ws --rm --network=none busybox:latest
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
none网络是个封闭的网络,使用了这种网络类型的容器无法在网络层被访问。封闭意味着隔离,一些对安全性要求高并且不需要
联网的应用可以使用none网络。比如某个容器的唯一用途是生成随机密码,就可以放到none网络中避免密码被窃取。
docker网络-Host网络
使用host网络的容器共享Docker host的网络栈,容器的网络配置与Docker host完全一样。可以通network=host指定使用host网络。可以通过以下示例看到,创建容器指定容器网络为host时,容器直接共享了Docker host的网络,能够获取到Docker host的网络信息。
[root@ws ~]# docker run -it --name ws --rm --network=host busybox:latest
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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 qlen 1000
link/ether 00:0c:29:a3:2a:18 brd ff:ff:ff:ff:ff:ff
inet 192.168.110.10/24 brd 192.168.110.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::8996:f378:c212:f88b/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue qlen 1000
link/ether 52:54:00:81:b2:5b brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 qlen 1000
link/ether 52:54:00:81:b2:5b brd ff:ff:ff:ff:ff:ff
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue
link/ether 02:42:6a:a8:65:b3 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:6aff:fea8:65b3/64 scope link
valid_lft forever preferred_lft forever
12: br-ce68bd41327a: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue
link/ether 02:42:4f:73:8f:7f brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-ce68bd41327a
valid_lft forever preferred_lft forever
inet6 fe80::42:4fff:fe73:8f7f/64 scope link
valid_lft forever preferred_lft forever
直接使用Docker host的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择host网络。当然不便之处就是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host上已经使用的端口就不能再用了。
这次我们使用httpd镜像创建容器,如下示例,可以看出容器中的80端口已经绑定到Docker host的
网络上,如果Docker host自身也有80端口的应用,那么就会与容器的80产生冲突。
[root@ws ~]# yum -y install httpd
[root@ws ~]# systemctl restart httpd.service
[root@ws ~]# docker run -it --name ws --rm --network=host nginx:latest
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/10/10 07:38:15 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
2025/10/10 07:38:15 [emerg] 1#1: bind() to [::]:80 failed (98: Address already in use)
docker网络-Bridge网络
Docker安装时会创建一个命名为docker0的linux bridge。如果不指定--network,创建的容器默认都会挂到docker0上。如下示例,docker0上没有任何其他网络设备。
[root@ws ~]# brctl show
bridge name bridge id STP enabled interfaces
br-ce68bd41327a 8000.02424f738f7f no
docker0 8000.02426aa865b3 no
virbr0 8000.52540081b25b yes virbr0-nic
我们新创建一个容器,一个新的网络接口veth98c678e被挂到了docker0上,veth98c678e就是新创建容器的虚
拟网卡。由于在创建容器的时候使用了--rm参数,退出容器时会自动的删除容器,需要开启多个终端进行示例操作。
[root@ws ~]# docker run -it --name ws --rm busybox:latest
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
79: eth0@if80: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
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
[root@ws ~]# brctl show
bridge name bridge id STP enabled interfaces
br-ce68bd41327a 8000.02424f738f7f no
docker0 8000.02426aa865b3 no veth407bcd5
virbr0 8000.52540081b25b yes virbr0-nic
容器有一个网卡eth0@if7。实际上eth0@if7和veth98c678e是一对veth pair。veth pair是一种成对出现的特殊网络设备,可以把它们想象成由一根虚拟网线连接起来的一对网卡,网卡的一头(eth0@if7)在容器中,(veth98c678e)挂在网桥 docker0 上,其效果就是将eth0@if7也挂在了 docker0 上。
我们还看到eth0@if7已经配置了IP:172.17.0.2,让我们通过docker network inspect bridge看一下
bridge网络的配置信息:
[root@ws ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "38c3edc3547795ad0e0f9f43e1a0cec0f51739f922ee9662ccc60366fb73e0f7",
"Created": "2025-10-10T11:20:57.726938968+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"0af53eb66decf4227473142693c9eed1141c8e97d3020589f277c48f522a1993": {
"Name": "ws",
"EndpointID": "65cf4b18473d1896042177bae1fc610b5bd2ac853e0a5adad2ccdd286cc606eb",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
原来bridge网络配置的subnet就是172.17.0.0/16,并且网关是172.17.0.1。容器创建时,Docker会
自动从172.17.0.0/16中分配一个IP,这里16位的掩码保证有足够多的IP可以供容器使用。
自定义Bridge网络
之前我们所使用的网络都是安装Docker时默认生成的网络。我们可通过bridge驱动创建类似前面默认的 bridge
网络,示例如下,网络名称为wsluoqi,类型为bridge,地址池为172.19.0.0/16,网关为172.19.0.1。
[root@ws ~]# docker network create --driver bridge --subnet 172.19.0.0/16 --gateway 172.19.0.1 wsluoqi
e4eff40797eb7be1f7e9d9087f89eb13109915b2bf7ff8c5463290c94e2d9cd8
[root@ws ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
38c3edc35477 bridge bridge local
ce68bd41327a harbor_harbor bridge local
4f77756645cb host host local
6fc2732f43cb none null local
e4eff40797eb wsluoqi bridge local
创建新的容器,指定使用wsluoqi网络,还可以使用--ip指定容器所使用的ip,这个ip要是wsluoqi地址池中的ip。如果不指定ip,那么wsluoqi会自动给容器分配ip。
[root@ws ~]# docker run -it --name ws --rm --network=wsluoqi --ip 172.19.0.100 busybox:latest
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
84: eth0@if85: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:13:00:64 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.100/16 brd 172.19.255.255 scope global eth0
valid_lft forever preferred_lft forever
如果创建一个容器a1,使用的默认bridge网络,再创建第二个容器a2,使用的wsluoqi网络,这种情况下两
个容器之间是不能够直接通讯的。只有指定了相同的网络的容器才能够互通。其实我们可以为容器指定多个网络,实现容器之间的通讯,示例如下,创建新的容器,指定wsluoqi网络,使用connect参数为该容器添加默认bridge网络,或者其他的bridge网络
[root@ws ~]# docker run -it --name a1 --rm busybox:latest
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
86: eth0@if87: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
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
[root@ws ~]# docker run -it --name a2 --rm --network=wsluoqi busybox:latest
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
88: eth0@if89: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@ws ~]# docker network connect bridge a2
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
88: eth0@if89: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0
valid_lft forever preferred_lft forever
90: eth1@if91: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth1
valid_lft forever preferred_lft forever
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.198 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.144 ms
64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.122 ms
64 bytes from 172.17.0.2: seq=3 ttl=64 time=0.176 ms
64 bytes from 172.17.0.2: seq=4 ttl=64 time=0.174 ms
64 bytes from 172.17.0.2: seq=5 ttl=64 time=0.102 ms
64 bytes from 172.17.0.2: seq=6 ttl=64 time=0.121 ms
^C
--- 172.17.0.2 ping statistics ---
7 packets transmitted, 7 packets received, 0% packet loss
round-trip min/avg/max = 0.102/0.148/0.198 ms
2 docker容器之间的访问方式
容器访问
容器之间访问可以使用以下方式
1、基于IP地址进行访问
2、基于容器名进行访问
3、多个容器共享同一个网络协议栈
注意:只有在同一个Docker网络中的容器才能够互相通讯;只有使用了默认的Bridge网络的容器是
无法使用基于容器名的方式进行容器互访的。
基于IP地址进行访问
创建一个新的容器a1,使用wsluoqi网络,容器获取的ip为172.19.0.2
[root@ws ~]# docker run -it --name a1 --rm --network=wsluoqi busybox:latest
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
92: eth0@if93: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0
valid_lft forever preferred_lft forever
再创建第二个容器a2,使用的也是wsluoqi网络,直接ping第一个容器a1的IP,示例如下。
[root@ws ~]# docker run -it --name a2 --rm --network=wsluoqi busybox:latest
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
94: eth0@if95: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:13:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.3/16 brd 172.19.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ping 172.19.0.2
PING 172.19.0.2 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.317 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.110 ms
64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.126 ms
^C
--- 172.19.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.110/0.184/0.317 ms
通过以上两个示例得知,在同一个网络中的容器,是可以使用IP进行互相访问的。
基于容器名进行访问
通过IP访问容器虽然满足了通信的需求,但还是不够灵活。因为我们在部署应用之前可能无法确定IP,部署之后再
指定要访问的IP会比较麻烦。对于这个问题,可以通过Docker自带的DNS服务解决。
从Docker 1.10版本开始,Docker daemon实现了一个内嵌的DNS server,使容器可以直接通过"容器名"通
信。方法很简单,只要在启动时用--name为容器命名就可以了,示例如下。
[root@ws ~]# docker run -it --name a1 --rm --network=wsluoqi busybox:latest
[root@ws ~]# docker run -it --name a2 --rm --network=wsluoqi busybox:latest
/ #
/ # ping a2
PING a2 (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.973 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.126 ms
^C
--- a2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.126/0.549/0.973 ms
/ #
通过以上示例得知,创建容器时,使用--name定义容器名称,当容器启动时,Docker daemon会把容器名与容
器获取的IP进行绑定,写入到Docker DNS中,这样容器之间访问就可以基于容器名实现了,如果容器停止了,该容器所对应的DNS信息就会从Docker DNS中删除。使用Docker DNS有个限制,只能在新创建的bridge网络中使用。
joined容器
Joined(联合)容器是另一种实现容器间通信的方式。joined容器非常特别,它可以使两个或多个容器
共享一个网络栈,共享网卡和配置信息,joined容器之间可以通过127.0.0.1直接通信。请看下面的例
子:
[root@ws ~]# docker run -itd --name a1 --network=wsluoqi busybox:latest
c91f89dac292ff31551c9190fa369b9d3e134beb0cc0300f52b3d4b6766782fc
[root@ws ~]# docker run -it --name a2 --rm --network=container:a1 busybox:latest
/ # ping a1
PING a1 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.187 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.088 ms
^C
--- a1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.088/0.137/0.187 ms
/ #
使用joined容器的方式实现容器间的通讯,需要注意的是两个容器之间的应用端口容易发生冲突,
两个容器共享一个网络栈,那么容器中的应用在运行时,绑定的IP也是一样。
容器访问外部
1、 容器int_1发送Ping报文包:172.17.0.3 > www.baidu.com。
2、docker0收到报文,发现是发送到外网的,交给NAT处理。
3、NAT将源地址换成ens36的IP:192.168.31.106 > www.baidu.com。
4、Ping包从ens36发送出去,到达 www.baidu.com。
通过 NAT,docker 实现了容器对外网的访问。

外部访问容器
如果想实现外部访问容器,可使用host网络,容器共享Docker host网络栈,就可以实现外部访问容
器。还有一种方法也是我们最常用的使用端口映射。