关于docker的安装文档,请参照上篇文章<docker系列二在宿主机上的安装和卸载>,本文主要针对docker中容器间的通讯方式以内部通讯进行说明。 [toc]html
自从docker容器出现,容器的网络通讯一直是众人关注的焦点,而容器的网络方案又能够分为两大部分:node
咱们在使用docker run建立 Docker 容器时,可使用--network=选项指定容器的网络模式,Docker 有如下 4 种网络模式:linux
当Docker进程启动时,会在主机上建立一个名为docker0的虚拟网桥,此主机上启动的Docker容器会链接到这个虚拟网桥上。虚拟网桥的工做方式和物理交换机相似,这样主机上的全部容器就经过交换机连在了一个二层网络中。从docker0子网中分配一个 IP 给容器使用,并设置 docker0 的 IP 地址为容器的默认网关。在主机上建立一对虚拟网卡veth pair设备,Docker 将 veth pair 设备的一端放在新建立的容器中,并命名为eth0(容器的网卡),另外一端放在主机中,以vethxxx这样相似的名字命名,并将这个网络设备加入到 docker0 网桥中。能够经过brctl show命令查看。安装brctl命令:nginx
yum install -y bridge-utils [root@linux-node4 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242d84b7159 no
bridge模式是 docker 的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker 实际是在iptables作了DNAT规则,实现端口转发功能。可使用iptables -t nat -vnL查看。bridge模式以下图所示: web
实验过程以下:docker
docker run --name docker1 nginx:1.13.12 docker run -d --name docker2 nginx:1.13.12
[root@linux-node4 ~]# [root@linux-node4 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242d84b7159 no veth8c72f4a vethf15e034 [root@linux-node4 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 75539117a127 nginx:1.13.12 "nginx -g 'daemon of…" About an hour ago Up About an hour 80/tcp docker2 69f1c16d206c nginx:1.13.12 "nginx -g 'daemon of…" About an hour ago Up About an hour 80/tcp docker1 [root@linux-node4 ~]# docker inspect 75539117a127 |grep 172.17 "Gateway": "172.17.0.1", "IPAddress": "172.17.0.3", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.3",
使用自定义的网桥网络
docker network create -d bridge my-net4 --subnet=192.168.100.1/24
建立一个自定义网桥-d指定模式为bridge,也能够为overlay,--subnet指定子网范围; 建立两个容器,并链接到咱们自建的网桥:curl
[root@linux-node4 ~]# docker run -d --name=my_test1 --network my-net4 nginx:1.13.12 ffc47de3992c52730ff2590b4b3903fe737521b9c713170d19b747fa2941c8b1
查看容器的网络地址,验证其ip地址是不是咱们自定义的网络。tcp
[root@linux-node4 ~]# docker inspect ffc47de3992 |grep 192 "Gateway": "192.168.100.1", "IPAddress": "192.168.100.2",
注意同一个网桥内的网络是相互能够通讯的,本篇不作过多说明。oop
若是启动容器的时候使用host模式,那么这个容器将不会得到一个独立的Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出本身的网卡,配置本身的 IP 等,而是使用宿主机的 IP 和端口。可是,容器的其余方面,如文件系统、进程列表等仍是和宿主机隔离的。 Host模式以下图所示:
验证步骤以下:
建立一个网络类型为host的容器 docker run -d --net=host --name=my_host1 nginx:1.13.12
由于nginx容器自己的端口号是80,因此咱们直接使用本地的接口来访问宿主机的ip和端口号。
[root@linux-node4 ~]# !curl curl http://127.0.0.1:80 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
若是使用这种网络模式的时候注意不要一个容器启动多个实例,会引发端口冲突不能起来,这种网络模型是没法使用nat转化的。 host模式有利也有弊,主要包括如下缺点:
- 容器没有隔离、独立的网络栈:容器由于与宿主机共享网络而争抢资源,而且容易崩溃也可能致使主机崩溃,这在生产环境是不容许发生的;
- 端口资源:docker host上已经使用的端口就不能再使用了 host模式的优势以下:
- 能够直接使用宿主机ip与外界通讯,无需额外进行nat转换,因为容器与外部通讯,再也不须要使用bridge等方式转发或者进行数据包的封装,性能上有很大优点。
这个模式指定新建立的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新建立的容器不会建立本身的网卡,配置本身的 IP,而是和一个指定的容器共享 IP、端口范围等。一样,两个容器除了网络方面,其余的如文件系统、进程列表等仍是隔离的。两个容器的进程能够经过 lo 网卡设备通讯。 Container模式示意图:
咱们仍是经过实验来验证这个结论吧,上文咱们已经建立了一个自定义网桥的容器,连接到这个容器里面便可
[root@linux-node4 ~]# docker run -d --name docker_con3 --net=container:ffc47de3992c busybox sleep 6000 933dd7fce1a67883869a6235c3a4f7835c983e079592087734715d05f6bd755e 进入容器内部验证网络是否跟预期一致: [root@linux-node4 ~]# docker exec -it 933dd7fce1a6 sh / # ip addr 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 33: eth0@if34: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:c0:a8:64:02 brd ff:ff:ff:ff:ff:ff inet 192.168.100.2/24 brd 192.168.100.255 scope global eth0 valid_lft forever preferred_lft forever / # route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.100.1 0.0.0.0 UG 0 0 0 eth0 192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
使用none模式,Docker 容器拥有本身的 Network Namespace,可是,并不为Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。须要咱们本身为 Docker 容器添加网卡、配置 IP 等。 None模式示意图:
[root@linux-node4 ~]# docker run -d --net=none --name docker_none2 busybox sleep 6000 247fb9eace8b5dedcb47b7f2015eb06f18d4eb67eb323560dcfaaf7ef1069773 网络状况验证: [root@linux-node4 ~]# docker exec -it 247fb9eace8b /bin/sh / # ip addr 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 / # route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface / #