Docker学习笔记(五)Docker同一宿主机网络

一、容器的网络基础

docker守护进程就是通过docker0为docker容器提供网络连接的各种服务。docker0实质事Linux的虚拟网桥。
在linux系统中,可以使用ifconfig命令查看docker0网桥信息:
在这里插入图片描述网桥是在OSI七层模型的数据链路层的网络设备,通过mac地址对网络进行划分,并且在不同网络直接传递数据,对于Linux的虚拟网桥:
(1)可以设置IP地址;
(2)相当于拥有一个隐藏的虚拟网卡。
docker守护进程在一个容器启动时,实际上要创建网络连接的两端;一端是在容器中的网络设备,另一端在运行docker容器的宿主机上,打开一个veth*的一个接口,用来实现docker0网桥与容器的网络通信。
例:我们启动一个nginx容器,查看是否产生新的网桥接口:
[docker@docker ~]$ docker run --name nginx -P docker.io/nginx
使用ifconfig命令查看是否产生新的网桥接口:
在这里插入图片描述上图最后红色的圈起来的信息就是我们启动容器产生的网络接口。
我们可以对docker0网桥IP、子网掩码等进行修改,命令格式为:
ifconfig docker0 IP netmask NETMASK
我们当前的docker0IP为172.17.0.1,netmask为255.255.0.0,我们将其修改为IP为172.1.1.1,netmask为255.255.255.0:
ifconfig docker0 172.1.1.1 netmask 255.255.255.0
使用ifconfig命令可以看到docker0网桥信息已经按照我们的命令修改了。
在这里插入图片描述但是这样使用命令修改网桥IP的话,只要一重启docker服务,网桥的IP又变回默认的172.17.0.1了,所以更彻底地修改网桥IP的方式为修改daemon.json配置文件:

[root@docker ~]# vi /etc/docker/daemon.json
{
  "registry-mirrors": ["https://z11csm7d.mirror.aliyuncs.com"],
  "bip":"192.168.55.1/24"
}

在该文件中加上标黄的"bip":“192.168.55.1/24”,保存修改,然后重启docker服务,再次查看docker0的IP:

[root@docker ~]# systemctl restart docker
[root@docker ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.55.1  netmask 255.255.255.0  broadcast 0.0.0.0
        ether 02:42:84:02:95:bb  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

二、创建自定义网络

docker提供三种自定义网络驱动:bridge,overlay,macvlan,其中overlay和macvlan用于创建跨主机的网络,所以本次主要学习bridge。
创建bridge网络命令格式为:

docker network create --driver bridge name

其中name是自己定义的网络名称,例如,新建一个名称为mynet的bridge网络:

[root@docker ~]# docker network create --driver bridge mynet
c1889b381f4852989db8e95b1349ee63b15a106adacf7a064b723e26ce386f2e
[root@docker ~]# 

以上,mynet网络就创建完成,使用brctl show 命令查看网桥信息,出现了br-c1889b381f48这个网桥,interfaces对应的值为空的,说明还没有容器使用此网桥。

[root@docker ~]# brctl show
bridge name	        bridge id		     STP enabled	 interfaces
br-c1889b381f48		8000.02421b372633	no		
docker0		        8000.0242579d6bb5	no		 vethff4147d

使用 docker network inspect mynet 查看mynet网络自动获取的IP段:

[root@docker ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "c1889b381f4852989db8e95b1349ee63b15a106adacf7a064b723e26ce386f2e",
        "Created": "2019-08-08T19:20:36.176677209+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
    }
]

以上可以看出,自动获取的IP段为172.18.0.0/16。
除了自动获取,我们也可以在创建网络时手动指定该网桥的IP网段,命令格式为:

[root@docker ~]# docker network create --driver bridge --subnet 172.19.0.0/16 --gateway 172.19.0.1 name
aeb83677bb933ce8c73d64167be595d683258e08f9c34b4dd09c4a8c2312843e

例如,创建一个mynet2网络:

[root@docker ~]# docker network create --driver bridge --subnet 172.19.0.0/16 --gateway 172.19.0.1 mynet2
aeb83677bb933ce8c73d64167be595d683258e08f9c34b4dd09c4a8c2312843e
[root@docker ~]# 

同样使用brctl show查看网桥信息,新出现了br-aeb83677bb93,interfaces同样显示无容器使用该网络:

[root@docker ~]# brctl show
bridge name	          bridge id		  STP enabled	interfaces
br-aeb83677bb93		8000.024260522e23	 no		
br-c1889b381f48		8000.02421b372633	 no		
docker0		        8000.0242579d6bb5	 no		    vethff4147d

三、自定义容器网络

我们创建了mynet和mynet2两个网络,现在我们使用–network=name指定nginx的容器分别使用两个网络:

[root@docker ~]# docker run --name nginx --network=mynet -P -d docker.io/nginx
37773b729b9b204102c07a4d78906e7575bd2f801a022c712da37f4329b74266
[root@docker ~]# docker run --name nginx2 --network=mynet2 -P -d docker.io/nginx
ad356866b0c59562b3d7f19162b4b750366c82eb72de854c978e1a229babdb2e

两个容器启动后,可以使用docker inspect nginx和docker inspect nginx2查看各自的IP:

[root@docker ~]# docker inspect nginx2
                    "NetworkID": "aeb83677bb933ce8c73d64167be595d683258e08f9c34b4dd09c4a8c2312843e",
                    "EndpointID": "cfa132b41284859a714ccd154291fbde5bc669dbff5066c922a2141adacbe38e",
                    "Gateway": "172.18.0.1",
                    "IPAddress": "172.18.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:13:00:02"
[root@docker ~]# docker inspect nginx2
                    "NetworkID": "c1889b381f4852989db8e95b1349ee63b15a106adacf7a064b723e26ce386f2e",
                    "EndpointID": "f010563c45c047147d9d67ee0f66e020d72e44ca7d2f571e66018ed1214ae8d7",
                    "Gateway": "172.19.0.1",
                    "IPAddress": "172.19.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:12:00:02"

我们再启动一个nginx3容器,使其和nginx2使用同一个网络:

[root@docker ~]# docker run --name nginx3 --network=mynet2 -P -d docker.io/nginx
[root@docker ~]# docker inspect nginx3
                    "NetworkID": "aeb83677bb933ce8c73d64167be595d683258e08f9c34b4dd09c4a8c2312843e",
                    "EndpointID": "d47e39352b22385db5b2e29776a1170a077bef68dfed02e835fc723cdd4ef5e0",
                    "Gateway": "172.19.0.1",
                    "IPAddress": "172.19.0.3",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:13:00:03"

这样我们的nginx2和nginx3处于同一网段,是可以互通的:

root@ad356866b0c5:/# curl 172.19.0.3
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>
</body>
</html>

但是nginx容器与nginx2和nginx3不处于同一网段,该怎么通信呢?

四、容器的互通

首先查看操作系统的路由表:

[root@docker ~]# ip  r
default via 192.168.0.1 dev eth0 proto dhcp 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-c1889b381f48 proto kernel scope link src 172.18.0.1 
172.19.0.0/16 dev br-aeb83677bb93 proto kernel scope link src 172.19.0.1 
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.187 metric 100

172.18.0.0和172.19.0.0两个网络都定义好了。
再查看操作系统是否打开了ip forwarding:

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

ip_forward已经是打开的,再查看iptables防火墙规则:

[root@docker ~]# iptables-save
-A DOCKER-ISOLATION -i br-c1889b381f48 -o br-aeb83677bb93 -j DROP
-A DOCKER-ISOLATION -i br-aeb83677bb93 -o br-c1889b381f48 -j DROP
-A DOCKER-ISOLATION -i docker0 -o br-aeb83677bb93 -j DROP
-A DOCKER-ISOLATION -i br-aeb83677bb93 -o docker0 -j DROP
-A DOCKER-ISOLATION -i docker0 -o br-c1889b381f48 -j DROP
-A DOCKER-ISOLATION -i br-c1889b381f48 -o docker0 -j DROP

以上内容可以看出iptables DROP掉了网桥docker0和其他网桥之间的流量,而且从DOCKER-ISOLATION规则的命名上就可以看出,docker在设计上就是为了隔离不同network上的容器,那么接下来:如何才能让nginx与nginx2和3之间通信呢?
答案是:为nginx增加一块mynet2的网卡,或者为nginx2和3增加一块mynet的网卡,具体操作如下:
先查看nginx容器的ID

[root@docker ~]# docker ps
CONTAINER ID        NAMES
5aa9f8bcb07f        nginx3
ad356866b0c5        nginx2
37773b729b9b        nginx

为该容器添加网卡:
[root@docker ~]# docker network connect mynet2 37773b729b9b
查看容器是否获取到新的IP

[root@docker ~]# docker inspect nginx
                    "NetworkID": "c1889b381f4852989db8e95b1349ee63b15a106adacf7a064b723e26ce386f2e",
                    "EndpointID": "ec53251b60176b207cfc578c8759f4d708b0114724fc220d4ae015897327bd56",
                    "Gateway": "172.18.0.1",
                    "IPAddress": "172.18.0.2",
……
                    "Gateway": "172.19.0.1",
                    "IPAddress": "172.19.0.4",

上,我们的nginx容器当前有两个网卡,所以有两个IP,现在应该能互通了:

root@37773b729b9b:/# curl 172.19.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
</body>
</html>
发布了21 篇原创文章 · 获赞 6 · 访问量 2846

猜你喜欢

转载自blog.csdn.net/weixin_43334786/article/details/105407890