Docker的网络

Docker网络模式

dockerhost单主机网络方案

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

//查看docker的原生网络

[root@docker01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b60f38e932ce        bridge              bridge              local
c742649ecf26        host                host                local
b4457d976de8        none                null                local

1.None网路

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

[root@docker01 ~]# docker run -itd --name none --network none busybox:latest

[root@docker01 ~]# docker exec -it none /bin/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

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 

[root@docker01 ~]# docker exec -it host 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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:0c:29:09:ff:79 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.20/24 brd 192.168.1.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::2e1:2d09:6720:477a/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue 
    link/ether 02:42:9d:a1:e5:bd 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
docker 0

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

[root@docker01 ~]# docker run -itd --name test1 busybox:latest 

[root@docker01 ~]# docker exec -it test1 /bin/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
4: eth0@if5: <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

容器默认使用的网络是docker0网络,docker0此时相当于一个路由器,基于此网络的容器,网段都是和docker0一致的。

4.自定义网络(brdige)

自带了一个ContainerDNSserver功能(域名解析)

基于bridge
//创建一个bridge网络

[root@docker01 ~]# docker network create -d bridge my_net1

[root@docker01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b60f38e932ce        bridge              bridge              local
c742649ecf26        host                host                local
39f17dde163e        my_net1             bridge              local
b4457d976de8        none                null                local

[root@docker01 ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
br-39f17dde163e		8000.02422ed76ea7	no		
docker0		8000.02429da1e5bd	no		veth0acc7b3

注意这里如果没有brctl,下载一下

[root@docker01 ~]# brctl show
-bash: brctl: command not found

[root@docker01 ~]# yum -y install bridge-utils
[root@docker01 ~]# docker run -itd --name test3 --network my_net1 busybox:latest

[root@docker01 ~]# docker run -itd --name test4 --network my_net1 busybox:latest

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

[root@docker01 ~]# docker exec -it test3 /bin/sh
/ # ping test4
PING test4 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.143 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.084 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.089 ms

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

[root@docker01 ~]# docker network create -d bridge --subnet 172.20.16.0/24 --gateway 172.20.16.1 my_net2
[root@docker01 ~]# docker run -itd --name test5 --network my_net2 --ip 172.20.16.6 busybox:latest

[root@docker01 ~]# docker run -itd --name test6 --network my_net2 --ip 172.20.16.8 busybox:latest

PS: 如果想要给容器指定IP地址,那么自定义网络的时候,必须指定网关gate和subnet网段选项。
在这里插入图片描述
思考: test2能ping的通 my_net1网关,但ping不通test3和test4,同理,test4能ping的通my_net2,但ping不通test5和test6。

这是因为iptabeles防火墙规则导致的,但不允许为了实现这个功能对防火墙进行操作,因为涉及安全,须谨慎,所以,我们采用另外的方法。

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

[root@docker01 ~]# docker network connect my_net1 test12

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

容器和容器之间。

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

[root@docker01 ~]# docker run -itd --name web1 busybox

[root@docker01 ~]# docker run -itd --name web2 --network container:web1 busybox:latest

[root@docker01 ~]# docker exec -it web1 /bin/sh
/ # echo 123456 > /tmp/index.html
/ # httpd -h /tmp/

[root@docker01 ~]# docker exec -it web2 /bin/sh
/ # wget -O - -q 127.0.0.1
123456

//这时会发现,两个容器的IP地址一样。

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

6.让外网能否访问容器

端口映射方法:

1)手动指定端口映射关系。

~]#  docker run -itd --name web3 -p 90:80 nginx:latest

2)从宿主机随机映射端口到容器。

~]# docker run -itd --name web4 -p 80 nginx:latest

3)从宿主机随机映射端口到容器,容器内所有暴露端口,都会一一映射。

~]# docker run -itd --name web5 -P nginx:latest

每一个映射的端口,host 都会启动一个 docker-proxy 进程来处理访问容器的流量

[root@docker01 ~]# ps -ef | grep docker-proxy
root       7703   7419  0 23:48 pts/0    00:00:00 grep --color=auto docker-proxy

猜你喜欢

转载自blog.csdn.net/hjyhjy0/article/details/113755846