Docker——6——Docker的网络

tech2023-06-18  110

Docker网络模式

dockerhost单主机网络方案

Docker 网络从覆盖范围可分为单个 host 上的容器网络和跨多个 host 的网络,先看单个host上的网络。

查看docker的原生网络(说法都对:三种原生网络 / 五种原生网络)

[root@docker01 ~]# docker network ls #三种原生网络 NETWORK ID NAME DRIVER SCOPE 6040b028e761 bridge bridge local 99a710f38345 host host local d70c283574f3 none null local [root@docker01 ~]# docker info #五种原生网络 …… Plugins: Network: bridge host macvlan null overlay ……

1、None网络

故名思议,none 网络就是什么都没有的网络。挂在这个网络下的容器除了 lo,没有其他任何网卡。容器创建时,可以通过 --network=none 指定使用 none 网络。

[root@docker01 ~]# docker run -itd --name none --network none busybox:latest [root@docker01 ~]# docker exec -it none sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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

PS: 用到None网络的容器,会发现他只有一个Loopback回环的网络,没有Mac地址、IP等信息,意味着他不能跟外界通信,是被隔离起来的网络。 使用场景: 这样一个封闭的网络有什么用呢? 其实还真有应用场景。封闭意味着隔离,一些对安全性要求高并且不需要联网的应用可以使用 none 网络。比如某个容器的唯一用途是生成随机密码,就可以放到 none 网络中避免密码被窃取。 当然大部分容器是需要网络的,接着看 host 网络。

2、Host网络

如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace ,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。 连接到 host 网络的容器共享 Docker host 的网络栈,容器的网络配置与 host 完全一样。可以通过 --network=host 指定使用 host 网络。

[root@docker01 ~]# docker run -itd --name host --network host busybox:latest 74f83bd3181b1311fe9c813ad37ed2d3ee7c8307c5df738992a982c6c0488b8c [root@docker01 ~]# docker exec -it host sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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:1e:20:7b brd ff:ff:ff:ff:ff:ff inet 192.168.1.128/24 brd 192.168.1.255 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::bd89:4eb5:6816:53f/64 scope link valid_lft forever preferred_lft forever 3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue qlen 1000 link/ether 52:54:00:b8:a1:7d 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:b8:a1:7d brd ff:ff:ff:ff:ff:ff 5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue link/ether 02:42:78:6c:28:3d 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 / # exit [root@docker01 ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 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 state UP qlen 1000 link/ether 00:0c:29:1e:20:7b brd ff:ff:ff:ff:ff:ff inet 192.168.1.128/24 brd 192.168.1.255 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::bd89:4eb5:6816:53f/64 scope link valid_lft forever preferred_lft forever 3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN qlen 1000 link/ether 52:54:00:b8:a1:7d 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 state DOWN qlen 1000 link/ether 52:54:00:b8:a1:7d brd ff:ff:ff:ff:ff:ff 5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN link/ether 02:42:78:6c:28:3d 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

PS: 用到Host网络的容器,他的网络跟宿主机的网络一模一样,那是因为,在创建这个容器之初,并没有对它的Net网络栈进行隔离,而是直接使用的宿主机的网络栈。 使用场景: 直接使用 Docker host 的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择 host 网络。当然不便之处就是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host 上已经使用的端口就不能再用了。

3、Bridge: 桥接网络

当 Docker 进程启动时,会在主机上创建一个名为 docker0 的虚拟网桥,此主机上启动的 Docker 容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。从 docker0 子网中分配一个 IP 给容器使用,并设置 docker0 的 IP 地址为容器的默认网关。在主机上创建一对虚拟网卡 veth pair 设备,Docker 将 veth pair 设备的一端放在新创建的容器中,并命名为 eth0 (容器的网卡),另一端放在主机中,以 vethxxx 这样类似的名字命名,并将这个网络设备加入到 docker0 网桥中。可以通过 brctl show 命令查看。

bridge 模式是 docker 的默认网络模式,不写–net 参数,就是 bridge 模式。使用 docker run -p 时,docker 实际是在 iptables 做了 DNAT 规则,实现端口转发功能。可以使用 iptables -t nat -vnL 查看。

[root@docker01 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.02421f4c362b no virbr0 8000.525400b8a17d yes virbr0-nic

docker0:在我们安装docker这个服务的时候,默认就会生产一张 docker0 的网卡,一般默认IP为172.17.0.1/16。

[root@docker01 ~]# docker run -itd --name test1 busybox:latest 44793267ca53e89ddc925b9a5fb9db9bb567af2febc382c7225318339a7a2907 [root@docker01 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242786c283d no veth0a3d08d virbr0 8000.525400b8a17d yes virbr0-nic [root@docker01 ~]# ip a …… 5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:78:6c:28:3d 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:78ff:fe6c:283d/64 scope link valid_lft forever preferred_lft forever 7: veth0a3d08d@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP link/ether 4e:81:87:91:bb:3c brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::4c81:87ff:fe91:bb3c/64 scope link valid_lft forever preferred_lft forever [root@docker01 ~]# docker exec -it test1 sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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 6: eth0@if7: <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

4、自定义网络(brdige)

自带了一个ContainerDNSserver功能(域名解析) 基于bridge 创建一个bridge网络

[root@docker01 ~]# docker network create -d bridge my_net1 [root@docker01 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE a580b13e4722 bridge bridge local 99a710f38345 host host local 4143a11a3600 my_net1 bridge local d70c283574f3 none null local [root@docker01 ~]# docker network inspect my_net1 #查看my_net1网络的详细信息 [ { "Name": "my_net1", "Id": "4143a11a3600c5f6eeefc237a3b900652bc06453edd2285e2a6c009b7d9a7b99", "Created": "2020-09-04T02:37:53.269030118+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ] [root@docker01 ~]# ip a …… 8: br-4143a11a3600: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN link/ether 02:42:01:7f:0a:af brd ff:ff:ff:ff:ff:ff inet 172.18.0.1/16 brd 172.18.255.255 scope global br-4143a11a3600 valid_lft forever preferred_lft forever [root@docker01 ~]# brctl show bridge name bridge id STP enabled interfaces br-66283650bb35 8000.0242cb23ed52 no docker0 8000.02421f4c362b no vethbc00b5a virbr0 8000.525400b8a17d yes virbr0-nic [root@docker01 ~]# docker run -itd --name test3 --network my_net1 busybox:latest [root@docker01 ~]# docker run -itd --name test4 --network my_net1 busybox:latest

自定义网络优点,它可以通过容器的名称通信

[root@docker01 ~]# docker exec -it test3 sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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 9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0 valid_lft forever preferred_lft forever / # ping test4 PING test4 (172.18.0.3): 56 data bytes 64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.064 ms 64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.061 ms ……

创建一个自定义网络,并且指定网关和网段

[root@docker01 ~]# docker network create -d bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net2

PS: 如果想要给容器指定IP地址,那么自定义网络的时候,必须指定网关gate和subnet网段选项。

[root@docker01 ~]# docker run -itd --name test5 --network my_net2 --ip 172.22.16.6 busybox:latest [root@docker01 ~]# docker run -itd --name test6 --network my_net2 --ip 172.22.16.8 busybox:latest [root@docker01 ~]# docker inspect test5 | grep IPAddress "SecondaryIPAddresses": null, "IPAddress": "", "IPAddress": "172.22.16.6", [root@docker01 ~]# docker inspect test6 | grep IPAddress "SecondaryIPAddresses": null, "IPAddress": "", "IPAddress": "172.22.16.8", [root@docker01 ~]# docker exec -it test5 sh / # ping test6 PING test6 (172.22.16.8): 56 data bytes 64 bytes from 172.22.16.8: seq=0 ttl=64 time=0.080 ms 64 bytes from 172.22.16.8: seq=1 ttl=64 time=0.085 ms ……

思考: test2能ping的通 my_net1网关,但ping不通test3和test4,同理,test4能ping的通my_net2,但ping不通test5和test6。 这是因为iptabeles防火墙规则导致的,(清空 iptables 规则命令:iptables -F)但不允许为了实现这个功能对防火墙进行操作,因为涉及安全,须谨慎,所以,采用另外的方法。

解决思路: 是在test2容器内新添加一块网卡,并且让它获取my_net1的网段。

[root@docker01 ~]# docker network connect my_net1 test2 [root@docker01 ~]# docker inspect test3 | grep IPAddress "SecondaryIPAddresses": null, "IPAddress": "", "IPAddress": "172.18.0.2", [root@docker01 ~]# docker exec -it test2 sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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 20: eth0@if21: <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 eth0 valid_lft forever preferred_lft forever 22: eth1@if23: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:12:00:04 brd ff:ff:ff:ff:ff:ff inet 172.18.0.4/16 brd 172.18.255.255 scope global eth1 valid_lft forever preferred_lft forever / # ping 172.18.0.2 #test3 IP PING 172.18.0.2 (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.233 ms 64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.089 ms …… / # ping test3 PING test3 (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.050 ms 64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.064 ms ……

PS: 同理如果想让 test4 ping通 test5 ,或者 test2 ping通 test5 只要在容器内添加相应的网卡即可

5、Join容器: container(共享网络协议栈)

容器和容器之间

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

[root@docker01 ~]# docker run -itd --name web1 busybox:latest [root@docker01 ~]# docker run -itd --name web2 --network container:web1 busybox:latest [root@docker01 ~]# docker inspect web1 | grep IPAddress "SecondaryIPAddresses": null, "IPAddress": "172.17.0.4", "IPAddress": "172.17.0.4", [root@docker01 ~]# docker inspect web2 | grep IPAddress "SecondaryIPAddresses": null, "IPAddress": "", 这时会发现,两个容器的IP地址一样 [root@docker01 ~]# docker exec -it web2 sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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 24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever [root@docker01 ~]# docker exec -it web1 sh / # echo 123456 > /tmp/index.html / # httpd -h /tmp/ / # exit [root@docker01 ~]# docker exec -it web2 sh / # wget -O - -q 127.0.0.1 123456

PS: 这种方法的使用场景:由于这种网络的特殊性,一般在运行同一个服务,并且合格服务需要做监控,已经日志收集、或者网络监控的时候,可以选择这种网络。

6、让外网能访问容器(端口映射)

端口映射方法: 1)手动指定端口映射关系——# -p 80(宿主机):80(容器) ~]# docker run -itd --name web3 -p 90:80 nginx:latest 2)从宿主机随机映射端口到容器。——# -p 80(容器) ~]# docker run -itd --name web4 -p 80 nginx:latest 3)从宿主机随机映射端口到容器,容器内所有暴露端口,都会一一映射。——# -P ~]# docker run -itd --name web5 -P nginx:latest 每一个映射的端口,host 都会启动一个 docker-proxy 进程来处理访问容器的流量

[root@docker01 ~]# docker run -itd --name web3 -p 80:80 nginx #-p 80(宿主机):80(容器) [root@docker01 ~]# ps -ef | grep docker-proxy root 45211 950 0 03:29 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.5 -container-port 80 root 45291 44221 0 03:29 pts/1 00:00:00 grep --color=auto docker-proxy [root@docker01 ~]# iptables-save -A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.5:80
最新回复(0)