容器网络管理

一、docker网络管理基础

123

1、docker0虚拟交换机

  • 查看网络的三个模式
[root@docker ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a74543c7bde1   bridge    bridge    local
138cedd6c719   host      host      local
51ca74dae4e4   none      null      local

# 这个bridge就是对应的docker0网桥

  • 创建一个容器的时候,默认使用的是桥接网络
# docker0 这个网络就是一个虚拟交换机(虚拟网桥),创建的容器都是在这个网段的里面的,也可以自己创建一个网络

[root@docker ~]# ifconfig docker0
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:83ff:fefa:a9  prefixlen 64  scopeid 0x20<link>
        ether 02:42:83:fa:00:a9  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5  bytes 526 (526.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

2、docker0网桥和容器接口关系

[root@docker ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED        STATUS         PORTS                                   NAMES
92f75978bf49   nginx     "/docker-entrypoint.…"   28 hours ago   Up 3 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   web
[root@docker ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.02422f40f62f	no		veth87c6d05

  • 创建一个容器后,docker0虚拟交换机上面会有一个接口连接着,然后这个接口也连接着容器,因此就能通信了

  • 创建一个容器后,就会生成一对veth虚拟接口,也就是多了一根线,一边连接着docker0网桥,一边连接着容器

img

[root@docker ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.02422f40f62f	no		vethe07dc3e
[root@docker ~]# 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
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:a5:d5:eb brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.200.10/24 brd 192.168.200.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fea5:d5eb/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:2f:40:f6:2f 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:2fff:fe40:f62f/64 scope link 
       valid_lft forever preferred_lft forever
7: vethe07dc3e@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 6e:d0:54:81:83:10 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::6cd0:54ff:fe81:8310/64 scope link 
       valid_lft forever preferred_lft forever

# docker0交换机上连接一个7号口,这个7号口又连接这个6号口

# 进入容器里面查看,连接的就是容器的网卡
[root@docker ~]# docker exec -ti web /bin/sh
/ # ip a
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
6: eth0@if7: <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

# 然而这个容器的网卡又连接这个7号口

# 也就是说这相当于是一个数据线,连接着docker0网桥和容器网卡

  • 这个docker0网桥又通过nat转发到主机的ens160网卡,ens160连接这个vmnet8,再次通过nat转发出去,实现访问外网的功能

二、三种网络模式

1、host模式(主机模式)

  • 会复制主机的所有网络,使用的是主机的ip地址
# 创建一个主机网络的容器,使用的主机的ip地址

[root@docker /]# docker run -tid --name q3 --network host alpine
6ea0b73fcba14c0cc5889d556f86b1ee8011e13b3dd0a4890e72a17e4d19e28a
[root@docker /]# docker exec -ti q3 /bin/sh
/ # ifconfig 
br-a25b80614af0 Link encap:Ethernet  HWaddr 02:42:82:83:53:6A  
          inet addr:192.111.10.1  Bcast:192.111.10.255  Mask:255.255.255.0
          inet6 addr: fe80::42:82ff:fe83:536a/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:328 (328.0 B)  TX bytes:1036 (1.0 KiB)

docker0   Link encap:Ethernet  HWaddr 02:42:2F:40:F6:2F  
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:2fff:fe40:f62f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3040 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2988 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:3525318 (3.3 MiB)  TX bytes:3056627 (2.9 MiB)

ens160    Link encap:Ethernet  HWaddr 00:0C:29:A5:D5:EB  
          inet addr:192.168.200.10  Bcast:192.168.200.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fea5:d5eb/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:27354 errors:0 dropped:0 overruns:0 frame:0
          TX packets:15130 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:19736683 (18.8 MiB)  TX bytes:5550775 (5.2 MiB)

2、桥接模式

  • 创建容器没有指定网络,默认使用的就是桥接模式

  • 可以自定义桥接网络,创建一个桥接网络

  • 也就相当于是创建了一个虚拟网桥(交换机)

  • docker0网桥和自定义网桥,是不同网段的,如果想要这2个网段通信的话,需要配置路由条目

# 相当于又创建了一个虚拟网桥(交换机)
[root@docker /]# docker network create --subnet 192.111.10.0/24 b1
a25b80614af0faf9243353e6a03207a3292b6ccc1a42f34ee8202a32245dec5d
[root@docker /]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a25b80614af0   b1        bridge    local
ef2509790e01   bridge    bridge    local
138cedd6c719   host      host      local
51ca74dae4e4   none      null      local
[root@docker /]# ifconfig 
br-a25b80614af0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.111.10.1  netmask 255.255.255.0  broadcast 192.111.10.255
        ether 02:42:82:83:53:6a  txqueuelen 0  (Ethernet)
        RX packets 1138  bytes 610080 (595.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1202  bytes 1297480 (1.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

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:2fff:fe40:f62f  prefixlen 64  scopeid 0x20<link>
        ether 02:42:2f:40:f6:2f  txqueuelen 0  (Ethernet)
        RX packets 3040  bytes 3525318 (3.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2988  bytes 3056627 (2.9 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


# 创建一个容器连接b1网桥
root@docker /]# docker run -tid --name b123 --network b1 alpine 
a6494b831b24da9f980f838ff8efce590bf88ac30403d8749233a76435dcf874
[root@docker /]# docker ps -a
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS                        PORTS                               NAMES
a6494b831b24   alpine      "/bin/sh"                2 seconds ago    Up 1 second                                                       b123

# 登录容器里面访问外网
[root@docker /]# docker exec -ti b123 /bin/sh
/ # ping qq.com
PING qq.com (203.205.254.157): 56 data bytes
64 bytes from 203.205.254.157: seq=0 ttl=127 time=173.330 ms

三、实验

1、搭建服务

  • 通过容器互联搭建一个wordpress

  • wordpress是要连接到数据上的

  • 需要wordpress和mysql镜像

  • 创建一个mysql容器后,数据是存放在哪里呢,如果容器被删除的话,数据也会被删除吗

  • 这个时候就需要-v 数据映射

  • 创建wordpress容器,需要指定数据库,对接数据库

WORDPRESS_DB_HOST # 博客系统要连接到哪台主机上(db所在的容器上)

WORDPRESS_DB_USER # 博客系统要使用哪个榕湖对接

WORDPRESS_DB_PASSWORD # 它的密码是什么

WORDPRESS_DB_NAME # 使用哪个数据

docker run -tid --name db --restart always -v /db:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=wordpress mysql

# 连接数据库主机使用的ip地址,后面实验ip地址会发生变化怎么办呢
docker run -tid --name blog -v /web:/var/www/html/ -p 80:80 -e WORDPRESS_DB_HOST=172.17.0.3 -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=root -e WORDPRESS_DB_NAME=wordpress wordpress


img

  • 访问到界面,就能说这个wordpress镜像和数据服务是正确的

  • 如果还需要输入用户名或者密码,主机等信息,就说明db容器是错误的

2、问题

  • 删除db容器,wordpress页面会出现错误,但是了数据文件都保存下来了,因此,可以再次创建db容器

  • 但是呢,还是有问题,就是再次创建db容器的ip会发生变化

  • 因此有一个方法,就是创建博客容器的时候,使用链接,而不是使用ip地址,使用link 链接

  • 以后blog容器就通过别名来进行访问了,

3、解决方法

  • --link选项
# 用法
# a容器是数据库,b容器是网站服务,b容器需要连接a容器

# 创建b容器时,建立一个--link a:a容器别名,之后就是通过这个别名来进行访问的a容器,因此,a容器的ip地址发生变化不影响

--link a容器:a容器别名 

  • 改进版
[root@docker /]# docker run -tid --name db --restart always -v /db:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=wordpress mysql


[root@docker /]# docker run -tid --name blog -v /web:/var/www/html/ -p 80:80 --link db:dbbm -e WORDPRESS_DB_HOST=dbbm -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=root -e WORDPRESS_DB_NAME=wordpress wordpress
73291467b5f05eceebe029d6086841cf97242d5b89f16cbd587c56d5fbb14ced

  • 因此的话,再次删除这个db容器,创建一个db容器,就能回复正常了,前提,名字不能变,数据的文件都存储在

  • 又出现了一个问题,删除了db容器后,随便创建一个容器,再次创建db容器,发现还是不行,这个时候重启docker服务,重启blog容器就恢复正常了

  • 使用了link的话,尽量不要删除,stop关闭db容器即可

# 关闭容器即可,删除容器不行

# 关闭db容器,创建一个别的容器,再次启动db容器,blog容器内的ip地址会发生变化

root@docker /]# docker ps -a
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                               NAMES
5d67b2274842   wordpress   "docker-entrypoint.s…"   10 seconds ago   Up 9 seconds    0.0.0.0:80->80/tcp, :::80->80/tcp   blog
ea2295a68980   mysql       "docker-entrypoint.s…"   21 seconds ago   Up 20 seconds   3306/tcp, 33060/tcp                 db
[root@docker /]# docker exec -ti blog  /bin/bash
root@5d67b2274842:/var/www/html# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2	dbbm ea2295a68980 db
172.17.0.3	5d67b2274842

# 关闭db容器,创建一个新的容器,占用ip地址
[root@docker ~]# docker inspect db | grep -i ipaddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",
[root@docker ~]# docker stop db
do^Hdb
[root@docker ~]# docker run -tid --name q1 alpine
b973b2901f1239189d52b1f92cd0536263277ace82d8d416aeef7a7061ee13c0
[root@docker ~]# docker start db
db
[root@docker ~]# docker inspect db | grep -i ipaddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.4",
                    "IPAddress": "172.17.0.4",


# blog里面的ip地址发生了变化
root@5d67b2274842:/var/www/html# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.4	dbbm ea2295a68980 db
172.17.0.3	5d67b2274842

# 这样就能进行访问了,尽量不要删除

4、link不便

  • 方法不常用,为了避免底层数据库ip地址发生变化,导致上层的应用无法访问,可以使用link指定一个别名

  • link是单向的,一但db的ip地址发生变化,上层的应用地址是无法跟着变化的,需要重新创建

问题

  • docker单节点,同网段通信

  • docker0网桥和自定义网桥,是不同网段的,如果想要这2个网段通信的话,需要配置路由条目

posted @ 2025-05-30 15:46  乔的港口  阅读(18)  评论(0)    收藏  举报