docker网络

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网络栈,就可以实现外部访问容

器。还有一种方法也是我们最常用的使用端口映射。

相关推荐
ServBay1 天前
告别面条代码,PSL 5.0 重构 PHP 性能与安全天花板
后端·php
Sheffield3 天前
Docker的跨主机服务与其对应的优缺点
linux·网络协议·docker
Sheffield4 天前
Alpine是什么,为什么是Docker首选?
linux·docker·容器
马艳泽4 天前
win10下运行Start Broker and Proxy报错解决
docker
JaguarJack4 天前
FrankenPHP 原生支持 Windows 了
后端·php·服务端
BingoGo4 天前
FrankenPHP 原生支持 Windows 了
后端·php
用户13573999256605 天前
Windows 从 0 搭建 WSL2 原生 AI 开发环境:Codex + Docker + VSCode
docker
vi_h5 天前
在 macOS 上通过 Docker 安装并运行 Ollama(详细可执行教程)
macos·docker·ollama
黑心老魔5 天前
通过 Docker 创建开发环境
docker·开发环境
JaguarJack5 天前
PHP 的异步编程 该怎么选择
后端·php·服务端