Docker网络 定义:Docker网络是Docker提供的一种用于在容器和容器之间、容器和外部网络之间提供网络功能的方式。Docker网络提供了容器间的安全、私有通信。
功能:容器间的互联和通信以及端口映射,容器IP变动时候可以通过服务名直接网络通信而不受到影响。
基本命令 1 2 3 4 5 6 7 8 Commands: connect Connect a container to a network #链接容器到指定网络 create Create a network #创建一个docker网络 disconnect Disconnect a container from a network #从某个网络中将指定容器移除 inspect Display detailed information on one or more networks #显示某个网络的详细信息 ls List networks #显示已经存在的docker网络 prune Remove all unused networks #移除掉未使用的网络 rm Remove one or more networks #移除某个或多个指定的网络
上述的部分命令包含子命令。可以通过–help查看
网络模式 通过使用docker network ls可以看到docker自动创建的三个网络分别是一下:
1 2 3 4 bridge模式:使用--network bridge指定,默认使用docker0 host模式:使用--network host指定 none模式:使用--network none指定 container模式:使用--network container:NAME或者容器ID指定 #该模式不是docker创建的需要自己指定。
bridge模式:为每个容器分配和设置IP等,并将容器链接到docker0的虚拟网桥上。
host模式:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
none模式:容器有独立的 Network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网桥连接,IP 等。几乎不使用这个。
container模式:新建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP,端口范围等。
用的最多的就是bridge和host两种网络模式,在创建docker网络时默认模式是bridge模式。
docker容器内部的IP有可能是会发生变动的。
案例说明
本章案例均使用typecho镜像来说明网络的各个模式,也可以使用别的镜像,只是恰巧在本地有一个typecho的镜像。
bridge模式 概述 Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。
1 2 3 4 5 6 7 8 [root@localhost ~]# docker network inspect ed17f204c15f | grep bridge "Name": "bridge", "Driver": "bridge", "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0"
1、Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
2、docker run 的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机ifconfig,就可以看到docker0和自己create的network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址
3、网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配。
整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);
每个容器实例内部也有一块网卡,每个接口叫eth0;
docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。
通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的ip,此时两个容器的网络是互通的。
案例 启动一个typecho的容器实例名为typecho-network-bridege.
在宿主机上ip addr来查看网络信息,可以看到如下信息,这是因为启动了一个typecho的docker容器示例,他的网络模式就是bridge模式。
进入到typecho容器示例内部查看网络情况如下。
可以看出docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。
host模式 概述 直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行NAT 转换。
容器将不会获得一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。
案例 重新启动一个typecho的容器实例名为typecho-network-host.
1 2 3 4 5 6 docker run -d \ --name=typecho-network-host \ --network host \ -e PHP_TZ=Asia/Shanghai \ -e PHP_MAX_EXECUTION_TIME=600 \ -p 80:80 80x86/typecho:latest
当执行完毕使会出现以下waring
WARNING: Published ports are discarded when using host network mode
这是因为在host模式下,使用的是宿主机的网络配置信息,不需要在指定端口映射。
通过inspect来查看容器的网络信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@localhost ~]# docker inspect typecho-network-host | tail -n 20 "host": { "IPAMConfig": null, "Links": null, "Aliases": null, "MacAddress": "", "NetworkID": "42171acac1d2c2f82078b43c5831b55097c9e05866efa09b434465619fff667d", "EndpointID": "dd109dbcbd74ff5c8883f680eed40562389975e76c72b6c26a93cfb7806a5344", "Gateway": "", "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "DriverOpts": null, "DNSNames": null } } } } ]
进入容器内部查看网络信息,可以发现,容器的网络信息和本地的信息一致。
此处由于网络信息较长,省略。
http://宿主机IP:80/
在CentOS里面用默认的火狐浏览器访问容器内的typecho服务看到访问成功,因为此时容器的IP借用主机的,所以容器共享宿主机网络IP,这样的好处是外部主机与容器可以直接通信。
none模式
该模式使用的很少。
概述 在none模式下,并不为Docker容器进行任何网络配置。 也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo需要我们自己为Docker容器添加网卡、配置IP等。
禁用网络功能,只有lo标识(就是127.0.0.1表示本地回环)
案例 以none模式启动一个typecho容器实例,实例名称为typecho-network-none.
1 2 3 4 5 6 docker run -d \ --name=typecho-network-none \ --network none \ -e PHP_TZ=Asia/Shanghai \ -e PHP_MAX_EXECUTION_TIME=600 \ -p 80:80 80x86/typecho:latest
在容器外部查看容器的网络信息如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@localhost ~]# docker inspect typecho-network-none | tail -n 20 "none": { "IPAMConfig": null, "Links": null, "Aliases": null, "MacAddress": "", "NetworkID": "7de51d8a81dd5910dedcc7c7bb79b79172f71097f3c66e812bb4d81d65f7fc7c", "EndpointID": "951841256eb35c74e6d0bf82da2e3fcaf4f13acf1fe899d1e0cc5b8c0e8ed6ff", "Gateway": "", "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "DriverOpts": null, "DNSNames": null } } } } ]
进入容器实例内部查看网络信息,可以看到容器的网络就只有一个lo。
1 2 3 4 5 6 7 8 [root@localhost ~]# docker exec -it typecho-network-none /bin/sh /app # ip addr 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
container模式 概述 新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。
案例 本案例使用ubuntu的镜像演示,由于typecho镜像在启动两个容器实例的时候会导致端口冲突。
以bridge模式启动一个ubuntu容器实例,实例名称为ubuntu-o。执行以下命令会打开一个连接ubuntu-o容器的伪终端。不要关闭。
1 docker run -it --name=ubuntu-o ubuntu:latest /bin/bash
A:查看ubuntu-o容器的网络信息,在连接ubuntu-o的伪终端中,输入ip addr命令发现无法找到命令。执行以下命令
1 2 apt-get update apt-get install -y iproute2
在伪终端中输入ip addr内容如下。
以下内容会根据你的系统变化。
1 2 3 4 5 6 7 8 9 10 11 root@d184d4bdf3d1:/# ip addr 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 14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
再启动一个ubuntu容器实例,实例名字为ubuntu-w,使用container网络模式,ubuntu-o和实例共享网络信息。执行以下命令会打开一个连接ubuntu-w容器的伪终端。不要关闭。
1 docker run -it --name=ubuntu-w --network container:ubuntu-o ubuntu:latest /bin/bash
查看容器是否成功启动
1 2 3 4 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3bee535ca29b ubuntu:latest "/bin/bash" 9 seconds ago Up 8 seconds ubuntu-w d184d4bdf3d1 ubuntu:latest "/bin/bash" 7 minutes ago Up 7 minutes ubuntu-o
在ubuntu-w伪终端界面查看网络信息,若出现上无法找到命令的话就执行A处的步骤。ubuntu-w容器的网络信息如下
1 2 3 4 5 6 7 8 9 10 11 root@d184d4bdf3d1:/# ip addr 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 14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
会发现ubuntu-w的网络信息和ubuntu-o的一样,是因为,ubuntu-w共享了ubuntu-o的网络。
若ubuntu-o容器实例停止运行,ubuntu-w的网络将丢失共享的网络配置剩下本地网络的回环地址配置信息。
自定义网络 概述 允许自定义容器之间的网络通信规则。自定义网络可以帮助你更好地控制容器的网络环境,例如隔离网络、创建私有网络等。
由于bridge模式在容器重启时可能会导致容器的网络配置IP信息发生变化,所以自定义网络可以使网络内的容器直接使用服务名通信。就解决了容器重启发生IP变化的问题。
案例
本案例只演示使用自定义网络后,网络内的容器可以直接调用的情况,由于不使用自定义网络只能通过IP通信这里不演示。
本案例同样使用ubuntu的镜像。
创建一个自定义的docker网络,网络名字为docker-study-network-custom,命令如下
1 2 3 4 5 6 7 8 9 [root@localhost ~]# docker network create docker-study-network-custom eea315734dc40c83f9c1d39fb0272f7a82d8be7db461cc7eb89fd5fe5ba5712f [root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 71eeefc97021 blinko-network bridge local ed17f204c15f bridge bridge local eea315734dc4 docker-study-network-custom bridge local 42171acac1d2 host host local 7de51d8a81dd none null local
创建两个ubuntu的实例,实例名分别为ubuntu-1,ubuntu-2。
1 2 docker run -it --name=ubuntu-1 --network docker-study-network-custom ubuntu:latest /bin/bash docker run -it --name=ubuntu-2 --network docker-study-network-custom ubuntu:latest /bin/bash
在ubuntu-2内ping ubuntu-1。
若提示ping命令不存在,在ubuntu-2的容器内执行以下命令
apt-get update
apt-get install iputils-ping
1 2 3 4 5 6 7 8 9 root@1631df68cf4d:/# ping ubuntu-1 PING ubuntu-1 (172.19.0.2) 56(84) bytes of data. 64 bytes from ubuntu-1.docker-study-network-custom (172.19.0.2): icmp_seq=1 ttl=64 time=0.075 ms 64 bytes from ubuntu-1.docker-study-network-custom (172.19.0.2): icmp_seq=2 ttl=64 time=0.108 ms 64 bytes from ubuntu-1.docker-study-network-custom (172.19.0.2): icmp_seq=3 ttl=64 time=0.045 ms ^C --- ubuntu-1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2005ms rtt min/avg/max/mdev = 0.045/0.076/0.108/0.025 ms
同样也可以直接ping ip地址。但是容器重启IP可能会发生变化,所以自定义网络解决了容器重启发生IP变化容器连通的问题。