docker-网络

Docker 的三个网络

  • none 网络:none网络的driver类型是null,IPAM字段为空。挂在none网络上的容器只有lo,无法与外界通信。
  • host 网络:挂在host网络上的容器共享宿主机的network namespace。即容器的网络配置与host网络配置完全一 样。
  • brige网络:Docker 就创建了在主机和所有容器之间一个虚拟共享网络 当创建一个 Docker 容器的时候,同时会创建 了一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包), 这对接 口 一端在容器内即 eth0; 另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT) 通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。

none 网络和host 网络

[root@docker ~]# docker network ls
NETWORK ID     NAME     DRIVER   SCOPE
a1b809382f0d   bridge   bridge   local
6ad21ed9ea1f   host     host     local
4e31521b27c6   none     null     local

[root@docker ~]# docker run -it --network=none busybox
/ #
/ # ifconfig
lo       Link encap:Local Loopback
         inet addr:127.0.0.1 Mask:255.0.0.0
         inet6 addr: ::1/128 Scope:Host
         UP LOOPBACK RUNNING MTU:65536 Metric:1
         RX packets:0 errors:0 dropped:0 overruns:0 frame:0
         TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:1000
         RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ #
/ # hostname
4027da12afaf

[root@docker ~]# docker run -it --network=host busybox     #容器网络与宿主机相同
/ #
/ # ip l
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
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
   link/ether 00:0c:29:33:15:f6 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue
   link/ether 02:42:02:fd:82:b3 brd ff:ff:ff:ff:ff:ff
/ #
/ # hostname                               #容器主机与宿主机相同
docker
/ #

brige网络

[root@docker ~]# cd /etc/yum.repos.d/
[root@docker yum.repos.d]# vim cloud.repo
[centos-openstack-victoria]
name=CentOS 8 - OpenStack victoria
baseurl=https://mirrors.aliyun.com/centos-vault/8-stream/cloud/x86_64/openstackvictoria/
enabled=1
gpgcheck=0
[root@docker
 yum.repos.d]# yum install -y bridge-utils

[root@docker ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02420be905a5       no

#当前 docker0 上没有任何其他网络设备
[root@docker ~]# docker run -itd --name busybox1 busybox
5225d246f751dbfc4cdf745675d9c79d3de1b91dd4174268c35e671b9f1b0c80
[root@docker ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02420be905a5       no             vethddb2744
#一个新的网络接口 vethddb2744 被挂到了 docker0 上, vethddb2744 就是新创建容器的虚拟网卡。

#容器的网络配置

[root@docker ~]# docker exec -it busybox1 sh
/ # 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
       
# 容器里的网卡是24号网卡名字叫eth0,对面是25号网卡
24: eth0@if25: <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
       
#bridge 网络的配置信息
[root@docker ~]# docker network inspect bridge

#网关是 172.17.0.1就是 docker0
[root@docker ~]# ip a | grep docker0
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
group default
   inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0

自定义容器网络

#bridge 驱动创建类似前面默认的 bridge 网络
[root@docker ~]# docker network create --driver bridge my_net
89f7bc11b602e84452ae01786113ac196a535f7296b9989ad941b3a48a5e6d04

[root@docker ~]# brctl show
bridge name             bridge id               STP enabled     interfaces
br-89f7bc11b602         8000.0242194d039e         no          
#my_net,看bridge 
name和刚才创建的my_net id一样
docker0                 8000.02420be905a5         no             vethddb2744    

#新增了一个网桥,查看一下 my_net 的配置信息
[root@docker ~]# docker network ls
[root@docker ~]# docker network inspect my_net

#指定 IP 网段
[root@docker ~]# docker network create --driver bridge --subnet 172.22.16.0/24 --
gateway 172.22.16.1 my_net2
ec761bc51778f67c2245af72fd969f00cd517ee617a10a70dc01904f9c10279d
[root@docker ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
br-89f7bc11b602         8000.0242194d039e       no                     
#my_net
br-ec761bc51778         8000.02427fa54b88       no                     
#my_net2
docker0         8000.02420be905a5       no             vethddb2744
[root@docker ~]# docker network inspect my_net2

[root@docker ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
br-89f7bc11b602         8000.0242194d039e       no                     #my_net
br-ec761bc51778         8000.02427fa54b88       no                     #my_net2
docker0         8000.02420be905a5       no             vethddb2744
#同时宿主机上出现了与网桥my_net,my_net2同名的网卡
#查看my_net2网卡
[root@docker ~]# ip a | grep br-ec761bc51778
27: br-ec761bc51778: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue 
state DOWN group default
   inet 172.22.16.1/24 brd 172.22.16.255 scope global br-ec761bc51778
   
#容器要使用新的网络,需要在启动时通过 --network 指定
[root@docker ~]# docker run -it --network=my_net2 --name busybox2 busybox
/ # 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
28: eth0@if29: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
   link/ether 02:42:ac:16:10:02 brd ff:ff:ff:ff:ff:ff
   inet 172.22.16.2/24 brd 172.22.16.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ctrl+P,ctrl+q退出容器
[root@docker ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
br-89f7bc11b602         8000.0242194d039e       no
br-ec761bc51778         8000.02427fa54b88       no     veth02dd704      
#my_net2上新增的接口veth02dd704连接容器busybox2
docker0         8000.02420be905a5       no             vethddb2744

#容器的 IP 都是 docker 自动从 subnet 中分配,指定一个静态 IP
[root@docker ~]# docker run -it --network=my_net2 --ip 172.22.16.8 --name 
busybox3 busybox
/ # 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
       30: eth0@if31: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
   link/ether 02:42:ac:16:10:08 brd ff:ff:ff:ff:ff:ff
   inet 172.22.16.8/24 brd 172.22.16.255 scope global eth0           
#确实是指定的IP
       valid_lft forever preferred_lft forever
/ # ctrl+P,ctrl+q退出容器
[root@docker ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
br-89f7bc11b602         8000.0242194d039e       no                        
#my_net
br-ec761bc51778         8000.02427fa54b88       no     veth02dd704       
#my_net2
                                                       veth5fbb7f6       
#veth5fbb7f6是连接busybox3
docker0         8000.02420be905a5       no             vethddb2744

容器之间的连通性

#busybox2、busybox3 容器都挂在 my_net2 上能够互通
# 登陆busybox2 ping busybox3
[root@docker ~]# docker exec -it busybox2 sh
/ # ifconfig eth0
eth0     Link encap:Ethernet HWaddr 02:42:AC:16:10:02
         inet addr:172.22.16.2 Bcast:172.22.16.255 Mask:255.255.255.0
         UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
         RX packets:18 errors:0 dropped:0 overruns:0 frame:0
         TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:0
         RX bytes:1436 (1.4 KiB) TX bytes:0 (0.0 B)
/ # ping -c 3 172.22.16.8
PING 172.22.16.8 (172.22.16.8): 56 data bytes
64 bytes from 172.22.16.8: seq=0 ttl=64 time=0.197 ms
64 bytes from 172.22.16.8: seq=1 ttl=64 time=0.137 ms
64 bytes from 172.22.16.8: seq=2 ttl=64 time=0.158 ms
--- 172.22.16.8 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.137/0.164/0.197 ms
/ #
# ping my_net2网关地址
/ # ping -c 3 172.22.16.1
PING 172.22.16.1 (172.22.16.1): 56 data bytes
64 bytes from 172.22.16.1: seq=0 ttl=64 time=0.149 ms
64 bytes from 172.22.16.1: seq=1 ttl=64 time=0.116 ms
64 bytes from 172.22.16.1: seq=2 ttl=64 time=0.182 ms
--- 172.22.16.1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.116/0.149/0.182 ms

#查看 host 上的路由表
[root@docker ~]# ip r
default via 192.168.108.2 dev ens160 proto static metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
172.18.0.0/16 dev br-a6eff42dc3c6 proto kernel scope link src 172.18.0.1 linkdown
172.22.16.0/24 dev br-c0fc7bdf8143 proto kernel scope link src 172.22.16.1
192.168.108.0/24 dev ens160 proto kernel scope link src 192.168.108.30 metric 100

[root@docker ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

#看 iptables
[root@docker ~]# iptables-save

#发现iptables DROP 掉了网桥 docker0 与 br-ec761bc51778(my_net2) 之间双向的流量。

#为 busybox1 容器添加一块 my_net2的网卡。这个可以通过 docker network connect 命令实现。

[root@docker ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED             STATUS             PORTS   
  NAMES
0899976a1c59   busybox   "sh"     About an hour ago   Up About an hour           
  busybox3
e9da18f962d6   busybox   "sh"     About an hour ago   Up About an hour           
  busybox2
5225d246f751   busybox   "sh"     About an hour ago   Up About an hour           
  busybox1

[root@docker ~]# docker network connect my_net2 busybox1

#验证
[root@docker ~]# docker exec -it busybox2 sh
/ # ping -c 3 172.22.16.3
PING 172.22.16.3 (172.22.16.3): 56 data bytes
64 bytes from 172.22.16.3: seq=0 ttl=64 time=0.199 ms
64 bytes from 172.22.16.3: seq=1 ttl=64 time=0.134 ms
64 bytes from 172.22.16.3: seq=2 ttl=64 time=0.141 ms

容器通信的三种方式

容器之间可通过 IP,Docker DNS Server 或 joined 容器三种方式通信。

  • IP 通信:同一个网络的网卡,具体做法是在容器创建时通过 --network 指定相应的网络,或者通过 docker network connect 将现有容器加入到指定网络。

  • Docker DNS Server:docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过“容器名”通信。方法很简单,只要在启动时用 --name 为容器命名就可以了。

    [root@docker ~]# docker run -it --network my_net2 --name bbox1 busybox
    / # 
    ctrl_p,ctrl_q退出容器
    
    [root@docker ~]# docker run -it --network my_net2 --name bbox2 busybox
    / # 
    ctrl_p,ctrl_q退出容器
    
    [root@docker ~]# docker exec -it bbox2 sh
    / #
    / # ping -c 3 bbox1
    PING bbox1 (172.22.16.2): 56 data bytes
    64 bytes from 172.22.16.2: seq=0 ttl=64 time=0.177 ms
    64 bytes from 172.22.16.2: seq=1 ttl=64 time=0.161 ms
    64 bytes from 172.22.16.2: seq=2 ttl=64 time=0.187 ms
    
    --- bbox1 ping statistics ---
    3 packets transmitted, 3 packets received, 0% packet loss
    round-trip min/avg/max = 0.161/0.175/0.187 ms
    
    #只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是无法使用 DNS 的
    
    [root@docker ~]# docker run -it --name bbox3 busybox
    / # 
    ctrl_p,ctrl_q退出容器
    
    [root@docker ~]# docker run -it --name bbox4 busybox
    / # 
    ctrl_p,ctrl_q退出容器
    
    [root@docker ~]# docker exec -it bbox4 sh
    / # ping -c 3 bbox3
    ping: bad address 'bbox3'
    / #
    
  • joined 容器:它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined 容器之间可以通过 127.0.0.1 直接通信。

    [root@docker ~]# docker run -d -it --name web1 httpd
    f7641c43eb7021724e869f77bd4541e909ebf0968fc35e6a43e8e674d046ef3f
    
    [root@docker ~]# docker exec -it web1 bash
    
    root@1d5181ce7a85:/usr/local/apache2# apt-get update
    
    root@1d5181ce7a85:/usr/local/apache2# apt-get install iproute2 -y
    
    root@1d5181ce7a85:/usr/local/apache2# ip a
    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
    18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
                  
    # 也可以直接通过hostname -I观察IP地址
    
    [root@docker ~]# docker run -it --network container:web1 busybox
    / # 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
    18: eth0@if19: <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
    / #
    
    / # wget 127.0.0.1
    Connecting to 127.0.0.1 (127.0.0.1:80)
    saving to 'index.html'
    index.html           100% |***************************|    45  0:00:00 ETA
    'index.html' saved
    / #
    / # cat index.html
    <html><body><h1>It works!</h1></body></html>
    / #
    

容器访问外部世界

  • 容器访问外部世界: docker host 上的 iptables 在 NAT 表中,有这么一条规则,如果网桥 docker0 收到来自 172.17.0.0/16 网段的外出包,把它交给 MASQUERADE 处理。而 MASQUERADE 的处理方式是将包的源地址替换成 host 的地址发送出去,即做了一次网络地址转换(NAT)

    • 主要过程:
    • busybox 发送 ping 包:172.17.0.2 > www.baidu.com。
    • docker0 收到包,发现是发送到外网的,交给 NAT 处理。
    • NAT 将源地址换成 ens160的 IP:192.168.108.30 > www.baidu.com。
    • ping 包从 ens160 发送出去,到达 www.baidu.com。
  • 外部世界访问容器:端口映射。

    [root@docker ~]# docker run -d -p 8080:80 httpd
    25b04cb7f6d6c012c609251a425475fcf7da03c93feb20c1d951eb45cb1ef79b
    [root@docker ~]#
    [root@docker ~]# curl 192.168.108.30:8080
    <html><body><h1>It works!</h1></body></html>
    

的,交给 NAT 处理。

  • NAT 将源地址换成 ens160的 IP:192.168.108.30 > www.baidu.com。

  • ping 包从 ens160 发送出去,到达 www.baidu.com。

  • 外部世界访问容器:端口映射。

    [root@docker ~]# docker run -d -p 8080:80 httpd
    25b04cb7f6d6c012c609251a425475fcf7da03c93feb20c1d951eb45cb1ef79b
    [root@docker ~]#
    [root@docker ~]# curl 192.168.108.30:8080
    <html><body><h1>It works!</h1></body></html>
    
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐