Docker ❉ 网络模式

本文深入探讨Docker的网络配置及自定义网络的创建方法。详细介绍了默认网络模式bridge的工作原理,以及如何创建自定义桥接网络来实现容器间的通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 docker的地址划分

  1. IP:172.17.42.1子网掩码:255.255.0.0
  2. MAC:02:42:ac:11:00:00到02:42:ac:11:fff
  3. 总共提供了65534个地址

二 Docker容器网络

完成docker engine的安装以后,docker会在每一个engine上面生成一个3种网络,他们是:bridge, none还有host

Docker 四种网络模式

  • 默认网络模式 - bridge(包括自定义网络)
  • 无网络模式 - none
  • 宿主网络模式 - host
  • 容器模式-container,将新部署的容器桥接到另一个容器上,使用桥接容器的网卡进行外部访问

默认网络模式 bridge

        多用于独立container之间的通信。

        docker0之所以说它是默认的网络,是由于当我们运行container的时候没有“显示”的指定网络时,我们的运行起来的container都会加入到这个“默认” docker0 网络。它的模式是bridge。 

 容器与主机网络示意图,docker0为主机为docker容器提供的网桥

 主机内默认网络示意图

 安装Docker时,它会自动创建三个网络


[root@slave1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
3972df127c1e   bridge    bridge    local
27174d698141   host      host      local
ea750354b2e5   none      null      local

        可以看到,driver类型为bridge的网络的名字也为bridge。在默认情况下,container都是使用的这个bridge的网络,此时container是可以访问外网和其他container的(需要通过IP地址)。

        这三个网络内置于Docker中。运行容器时,可以使用该--network标志指定容器应连接到的网络。除非您使用该docker run --network=<NETWORK>选项另行指定,否则Docker守护程序默认情况下将容器连接到此网络。

        主机上的ifconfig命令将此桥接器视为主机网络堆栈的一部分。

[root@slave1 ~]# ifconfig 
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:3fff:fe0a:90ea  prefixlen 64  scopeid 0x20<link>
        ether 02:42:3f:0a:90:ea  txqueuelen 0  (Ethernet)
        RX packets 106  bytes 12121 (11.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 120  bytes 18898 (18.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

        默认的名为bridge的网络是有很多限制的,为此,我们可以自行创建bridge类型的网络。默认的bridge网络与自建bridge网络有以下区别:

  • 端口不会自行发布,必须使用-p参数才能为外界访问,而使用自建的bridge网络时,container的端口可直接被相同网络下的其他container访问。
  • container之间的如果需要通过名字访问,需要`--link`参数(不建议)

        连接到默认bridge网络的容器可以通过IP地址相互通信。Docker不支持默认网桥上的自动服务发现。如果希望容器能够按容器名称解析IP地址,则应使用用户定义的网络。您可以使用旧版docker run --link选项将两个容器链接在一起,但在大多数情况下不建议这样做。

2  无网络模式 none

        所有加入到这个网络模式中的container,都"不能”进行网络通信。貌似有点鸡肋,但是可以用作本地存储数据。

宿主网络模式 host

        直接使用宿主机的网络,端口也使用宿主机的 这种网络模式将container与宿主机的网络相连通,虽然很直接,但是却破获了container的隔离性,因此也比较鸡肋

自定义网络

        之前介绍的3种自带的网络模式有各自的局限性,因此,docker推荐大家自定义网络。通过自定义网络,我们可以实现“服务发现”与“DNS解析”。 docker 允许我们创建3种类型的自定义网络,bridgeoverlayMACVLAN(目前我还没有用到)。

  • bridge:Bridge模式是Docker默认的网络模式,当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,用来连接宿主机和容器,此主机上的Docker容器都会连接到这个虚拟网桥上
  • overlay:当有多个docker主机时,跨主机的container通信
  • macvlan:每个container都有一个虚拟的MAC地址

 (一)创建自己的桥接网络

Docker Engine本身支持桥接网络和覆盖网络。桥接网络仅限于运行Docker Engine的单个主机。覆盖网络可以包含多个主机,是一个更高级的主题。在本例中,您将创建一个桥接网络:

# 使用docker network create创建一个网络
[root@slave1 ~]# docker network create -d bridge test_bridge
873f4523c27072f8ca7961f5107d5969a745f8137c898c5e14a85e045a6a454b
# 该-d标志告诉Docker将bridge驱动程序用于新网络。您可以将此标志保留为此标志bridge的默认值
# 继续列出机器上的网络
[root@slave1 ~]# docker network ls
NETWORK ID     NAME          DRIVER    SCOPE
3972df127c1e   bridge        bridge    local
27174d698141   host          host      local
ea750354b2e5   none          null      local
873f4523c270   test_bridge   bridge    local
[root@slave1 ~]# ifconfig
br-873f4523c270: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        inet6 fe80::42:53ff:fe89:a0a  prefixlen 64  scopeid 0x20<link>
        ether 02:42:53:89:0a:0a  txqueuelen 0  (Ethernet)
        RX packets 1495  bytes 83006 (81.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1724  bytes 8706828 (8.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

(二)将容器添加到网络

要构建协同工作但安全地执行的Web应用程序,请创建网络。根据定义,网络为容器提供完全隔离。首次运行容器时,可以将容器添加到网络中。

# 创建一个容器
[root@slave1 ~]# docker run -d --network=test_bridge --name db redis:5.0-alpine
014b59d6e35d7b383a76af8a3a899fc02d229d8ea01dd908da2c1d0e61e6b7d8
# 利用`--network`或者`--net`启动容器提供服务
# 启动运行PostgreSQL数据库的容器并将其传递给它--net=test_bridge以将其连接到新网络
# 或者使用全名:docker run -d --network=tinywan_bridge  --network-alias db redis:5.0-alpine
# 通过选项--network-alias将取名的db起了一个别名

# 检查test_bridge你会发现它附有一个容器。还可以检查容器以查看其连接位置
[root@slave1 ~]# docker inspect --format='{{json .NetworkSettings.Networks}}'  db
{"test_bridge":{"IPAMConfig":null,"Links":null,"Aliases":["014b59d6e35d"],"NetworkID":"873f4523c27072f8ca7961f5107d5969a745f8137c898c5e14a85e045a6a454b","EndpointID":"78724e1a772f7aa1a5c0135c2639ad5b61c87264c587196c3d2a8cf7e2a7e2c9","Gateway":"172.18.0.1","IPAddress":"172.18.0.2","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:12:00:02","DriverOpts":null}}
# 可以看到这个容器的IP是172.18.0.2,网关是172.18.0.1
# 这已经不是默认的那个172.17.0.0/24网段了

另外创建一个默认网络的容器,创建时不指定网络参数即可

# 继续开始熟悉的Web应用程序,这次不指定网络
[root@slave1 ~]# docker run -d --name web nginx

# 检查应用程序,会发现web正在默认bridge网络中运行
[root@slave1 ~]# docker inspect --format='{{json .NetworkSettings.Networks}}'  web
{"bridge":{"IPAMConfig":null,"Links":null,"Aliases":null,"NetworkID":"3972df127c1ef8bd8ca05ee8ee7cc2b75715947cd5a4725a9424fc4ab4acb2d4","EndpointID":"f3b8a91790ee0324674e3c1d4f44fb022412a924231915023a42ecd355efb0ae","Gateway":"172.17.0.1","IPAddress":"172.17.0.4","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:11:00:04","DriverOpts":null}}

# 查看网址
[root@slave1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web
172.17.0.4

现在,打开运行web容器的shell

[root@slave1 ~]# docker exec -it de85ec814330 bash
root@de85ec814330:/# ping 172.18.0.1
bash: ping: command not found
# nginx 镜像默认是没有安装 ping和ipconfig命令的,这里需要手动安装
# 1、更新安装包: apt-get update
# 2、安装网络包: apt-get install tools-net
# 3、安装ping包: apt-get install iputils-ping
# 第二个命令执行如下,但是不影响结果,我们只要能测试ping命令即可
root@de85ec814330:/# apt-get install tools-net
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package tools-net

# 测试网关是否可达
root@de85ec814330:/# ping 172.18.0.1
PING 172.18.0.1 (172.18.0.1) 56(84) bytes of data.
64 bytes from 172.18.0.1: icmp_seq=1 ttl=64 time=0.049 ms
64 bytes from 172.18.0.1: icmp_seq=2 ttl=64 time=0.061 ms
64 bytes from 172.18.0.1: icmp_seq=3 ttl=64 time=0.082 ms
64 bytes from 172.18.0.1: icmp_seq=4 ttl=64 time=0.078 ms
64 bytes from 172.18.0.1: icmp_seq=5 ttl=64 time=0.051 ms
64 bytes from 172.18.0.1: icmp_seq=6 ttl=64 time=0.049 ms
^C
--- 172.18.0.1 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5003ms
rtt min/avg/max/mdev = 0.049/0.061/0.082/0.013 ms
# 测试另一个网络的容器不可达
root@de85ec814330:/# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
^C
--- 172.18.0.2 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2000ms

(三)扩展

        Docker网络允许您将容器附加到任意数量的网络。我们还可以附加已在运行的容器。继续并将正在运行的web应用程序附加到test_bridge

比如要让上面不同网络的容器互相连接,可以用下面的步骤

# 将web加入到test_bridge
[root@slave1 ~]# docker network connect test_bridge web

# 查看web发现多了一个虚拟网口
[root@slave1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}} {{.IPAddress}}{{end}}' web
 172.17.0.4 172.18.0.3

# 进入这个容器发现分别使用不同的网卡ping通db和同网段的容器(实验中以网关代替)
[root@slave1 ~]# docker exec -it web bash
root@de85ec814330:/# ping db
PING db (172.18.0.2) 56(84) bytes of data.
64 bytes from db.test_bridge (172.18.0.2): icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from db.test_bridge (172.18.0.2): icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from db.test_bridge (172.18.0.2): icmp_seq=3 ttl=64 time=0.090 ms
64 bytes from db.test_bridge (172.18.0.2): icmp_seq=4 ttl=64 time=0.059 ms
^C
--- db ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 0.052/0.065/0.090/0.014 ms
root@de85ec814330:/# ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data.
64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.119 ms
64 bytes from 172.17.0.1: icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from 172.17.0.1: icmp_seq=3 ttl=64 time=0.052 ms
^C
--- 172.17.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.052/0.077/0.119/0.029 ms

添加后网络如图

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值