1. docker网络介绍
大量的互联网应用服务需要多个服务组件,这往往需要多个容器之间通过网络通信进行相互配合。
docker 网络从覆盖范围可分为单个 host 上的容器网络和跨多个 host 的网络。
docker 目前提供了映射容器端口到宿主主机和容器互联机制(映射)来为容器提供网络服务,在启动容器的时候,如果不指定参数,在容器外部是没有办法通过网络来访问容器内部的网络应用和服务的。
docker 安装时会自动在host上创建三个网络,查看一下docker网络:
[root@alph ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 59cb3737df3c bridge bridge local 8b9081147227 host host local ea6732b465e8 none null local [root@alph ~]#
2. docker none网络
none 网络就是什么都没有的网络。挂在这个网络下的容器除了 lo(本地回环地址),没有其他任何网卡。容器创建时,可以通过 --network=none 指定使用 none 网络
启动容器: [root@alph ~]# docker run -itd --network=none --name box reg.yunwei.edu/learn/httpd:latest 18f6521f1ae21775203a3d0efe40b62082a4edb637e074292ab6f6e665cee361 查看: 18f6521f1ae21775203a3d0efe40b62082a4edb637e074292ab6f6e665cee361 [root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 18f6521f1ae2 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 7 seconds ago Up 7 seconds box 进入容器: [root@alph ~]# docker exec -it 18f6521f1ae2 /bin/bash 查看ip root@18f6521f1ae2:/usr/local/apache2# ip a #仅有lo 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 root@18f6521f1ae2:/usr/local/apache2# ^C root@18f6521f1ae2:/usr/local/apache2#
none 网络的应用
封闭的网络意味着隔离,一些对安全性要求高并且不需要联网的应用可以使用 none 网络。
比如某个容器的唯一用途是生成随机密码,就可以放到 none 网络中避免密码被窃取。
3. host网络
连接到 host 网络的容器,共享 docker host 的网络栈,容器的网络配置与 host 完全一样。可以通过 --network=host 指定使用 host 网络。
[root@alph ~]# docker run -itd --network=host --name box2 reg.yunwei.edu/learn/httpd:latest [root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d478bbdb1ef8 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 23 seconds ago Up 22 seconds box2 18f6521f1ae2 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" About an hour ago Up About an hour box [root@alph ~]# docker exec -it d478bbdb1ef8 /bin/sh # ip a 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 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:50:56:37:0c:29 brd ff:ff:ff:ff:ff:ff inet 192.168.16.88/24 brd 192.168.16.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:25:8a:98:c6 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:25ff:fe8a:98c6/64 scope link valid_lft forever preferred_lft forever # hostname alph
在容器中可以看到 host 的所有网卡,并且连 hostname 也是 host 的。
直接使用 Docker host 的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,就可以选择 host 网络。
当然不便之处就是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host 上已经使用的端口就不能再用了。
Docker host 的另一个用途是让容器可以直接配置 host 网路。比如某些跨 host 的网络解决方案,其本身也是以容器方式运行的,这些方案需要对网络进行配置,比如管理 iptables。
4. docker bridge 网络
docker 安装时会创建一个 命名为 docker0 的 linux bridge。如果不指定--network,创建的容器默认都会挂到 docker0 上。
[root@alph ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242258a98c6 no
当前docker0 上没有其他网络设备,创建一个容器查看变化。
[root@alph ~]# docker run -itd --name box3 reg.yunwei.edu/learn/httpd:latest 5ddc5295e266aaf49c897710ccbb1e02273f49b15afd1bdfb8f4dfffc1de9dfe [root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5ddc5295e266 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 17 seconds ago Up 17 seconds 80/tcp box3 d478bbdb1ef8 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 9 minutes ago Up 9 minutes box2 18f6521f1ae2 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" About an hour ago Up About an hour box [root@alph ~]# docker exec -it 5ddc5295e266 /bin/bash root@5ddc5295e266:/usr/local/apache2# ip a 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 6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 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 [root@alph ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242258a98c6 no vethaecb9c8
一个新的网络接口 vethaecb9c8 被挂到了 docker0 上,vethaecb9c8就是新创建容器的虚拟网卡。eth0@if7和vethaecb9c8是一对 veth pair。veth pair 是一种成对出现的特殊网络设备,可以把它们想象成由一根虚拟网线连接起来的一对网卡,网卡的一头(eth0@if7)在容器中,另一头(vethaecb9c8)挂在网桥 docker0 上,其效果就是将 eth0@if7 也挂在了 docker0 上。
eth0@if7已经配置了ip 172.17.0.2/16,这个网段有配置信息network inspect bridge 决定。
[root@alph ~]# docker network inspect bridge [ { "Name": "bridge", "Id": "59cb3737df3cea7308084fb5c112836f55520e8546cd7e7603949ab4db36a0e4", "Created": "2019-07-15T22:10:23.832317973+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "5ddc5295e266aaf49c897710ccbb1e02273f49b15afd1bdfb8f4dfffc1de9dfe": { "Name": "box3", "EndpointID": "cb51e0323762eed6e4ea588cf64f9b0f06ffc79642c71e98008e54b3a3923341", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }, "Options": { "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", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]
5. 自定义创建网络
可通过 bridge 驱动创建类似前面默认的 bridge 网络
(1)利用bridge驱动创建名为my-net2网桥(docker会自动分配网段):
[root@alph ~]# docker network create --driver bridge my-net2
966e69c70ce3eb189be4d993f97e6c572b470f7c74f8104059e27bd04cf9c95a
(2)查看一下当前 host 的网络结构变化:
[root@alph ~]# docker network list NETWORK ID NAME DRIVER SCOPE 59cb3737df3c bridge bridge local 8b9081147227 host host local 966e69c70ce3 my-net2 bridge local ea6732b465e8 none null local
(3)查看容器bridge网桥配置(bridge就是容器和网桥形成一对veth pair)
[root@alph ~]# docker network inspect bridge my-net2 { "Name": "my-net2", "Id": "966e69c70ce3eb189be4d993f97e6c572b470f7c74f8104059e27bd04cf9c95a", "Created": "2019-07-16T02:25:29.664999007+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", #16为掩码。提供更多的服务 "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ]
删除网络用命令 rm
[root@alph ~]# docker network create --driver bridge my-net3 596fc585538f6862425300dcdc35b62a759f8b11feb249d142492c5519a6a0c2 [root@alph ~]# docker network list NETWORK ID NAME DRIVER SCOPE 59cb3737df3c bridge bridge local 8b9081147227 host host local 966e69c70ce3 my-net2 bridge local 596fc585538f my-net3 bridge local ea6732b465e8 none null local [root@alph ~]# docker rm my-net3 Error: No such container: my-net3 [root@alph ~]# docker network rm my-net3 my-net3 [root@alph ~]# docker network list NETWORK ID NAME DRIVER SCOPE 59cb3737df3c bridge bridge local 8b9081147227 host host local 966e69c70ce3 my-net2 bridge local ea6732b465e8 none null local
(4)利用bridge驱动创建名为my-net3网桥(用户自定义网段及网关)
[root@alph ~]# docker run -itd --network=my-net3 --name box4 reg.yunwei.edu/learn/httpd:latest 1fd7e0d3e08345da6e7259fbf6dcb0bf95861ec457236e81125737840032c539 [root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1fd7e0d3e083 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 18 seconds ago Up 17 seconds 80/tcp box4 5ddc5295e266 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" About an hour ago Up About an hour 80/tcp box3 d478bbdb1ef8 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" About an hour ago Up About an hour box2 18f6521f1ae2 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 2 hours ago Up 2 hours box
(5)启动容器使用新建的my-net3网络
[root@alph ~]# docker exec -it box4 "docker exec" requires at least 2 arguments. See 'docker exec --help'. Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] [flags] Run a command in a running container [root@alph ~]# docker exec -it box4 /bin/sh # ip a 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 19: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:16:01:02 brd ff:ff:ff:ff:ff:ff inet 172.22.1.2/24 brd 172.22.1.255 scope global eth0 #自定义的网段 valid_lft forever preferred_lft forever
(6)启动容器使用my-net3网络并指定ip(只有使用 --subnet 创建的网络才能指定静态 IP,如果是docker自动分配的网段不可以指定ip)
[root@alph ~]# docker run -it --network=my-net3 --ip 172.22.1.10 reg.yunwei.edu/learn/httpd:latest /bin/sh # ip a 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 21: eth0@if22: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:16:01:0a brd ff:ff:ff:ff:ff:ff inet 172.22.1.10/24 brd 172.22.1.255 scope global eth0 valid_lft forever preferred_lft forever
(7)让已启动不同vlan的box容器,可以连接到my-net2(其实在box中新建了my-net2的网卡)
[root@alph ~]# docker network connect my-net2 box4 [root@alph ~]# docker exec -it box4 /bin/sh # ip a 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 19: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:16:01:02 brd ff:ff:ff:ff:ff:ff inet 172.22.1.2/24 brd 172.22.1.255 scope global eth0 valid_lft forever preferred_lft forever 23: eth1@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default #连接到box2的网卡 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 eth1 valid_lft forever preferred_lft forever #
(8)使用--name指定启动容器名字,可以使用docker自带DNS通信,但只能工作在user-defined 网络,默认的 bridge 网络是无法使用 DNS 的。
docker run -it --network=my_net2 --name=bbox1 busybox
docker run -it --network=my_net2 --name=bbox2 busybox
(9)容器之间的网络互联
a). 首先创建一个 db 容器
[root@alph ~]# docker run -dti --name db reg.yunwei.edu/learn/centos:7 2b9cdc455352f8a5e2da50db61fef706089f4abe7ba7c4b91033cc2a55a55bf8
b). 创建一个 web 容器,并使其连接到 db
[root@alph ~]# docker run -dti --name web --link db:dblink reg.yunwei.edu/learn/centos:7 /bin/bash 40bba17b3dfe2ad01d6b80d78230c975e127340170d15a49e8f7c905bbd075fe
-link db:dblink 实际是连接对端的名字和这个链接的名字,也就是和 db 容器建立一个叫做 dblink 的链接
c). 查看链接的情况
[root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 40bba17b3dfe reg.yunwei.edu/learn/centos:7 "/bin/bash" About a minute ago Up About a minute web 2b9cdc455352 reg.yunwei.edu/learn/centos:7 "/bin/bash" About a minute ago Up About a minute db
d). 使用 ping 命令来测试网络链接的情况
[root@alph ~]# docker exec -it 40bba17b3dfe /bin/bash [root@40bba17b3dfe /]# ping db PING dblink (172.17.0.3) 56(84) bytes of data. 64 bytes from dblink (172.17.0.3): icmp_seq=1 ttl=64 time=48.5 ms 64 bytes from dblink (172.17.0.3): icmp_seq=2 ttl=64 time=0.058 ms
再换到db容器来ping web容器,因为连接是单向的,因此是ping不同的
[root@alph ~]# docker exec -it db /bin/sh sh-4.2# ping web
(10)容器端口映射
在启动容器的时候,如果不指定参数,在容器外部是没有办法通过网络来访问容器内部的网络应用和服务的。
当容器需要通信时,我们可以使用 -P (大)和 -p (小)来指定端口映射。
-P(大) : Docker 会随机映射一个 49000 ~ 49900 的端口到容器内部开放的网络端口
-p (小):则可以指定要映射的端口,并且在一个指定的端口上只可以绑定一个容器。
支持的格式有
IP : HostPort : ContainerPort (将Host端口映射给Container)
IP : : ContainerPort (随机生成一个端口号映射为Container)
IP : HostPort : (类似的,让容器随机生成一个端口)
a)映射所有接口地址,此时绑定本地所有接口上的 5000 到容器的 5000 接口,访问任何一个本地接口的 5000 ,都会直接访问到容器内部
[root@alph ~]# docker run -itd -p 8081 --name http reg.yunwei.edu/learn/httpd c69494d7692d9cd5aa0ce24c286ad607adb9879f35cb8ce214a1002d8c24c336
通过访问宿主机的端口号来访问容器
尝试在容器http更改html文件,再刷新查看
[root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2d7cc376dd27 reg.yunwei.edu/learn/httpd "httpd-foreground" About a minute ago Up About a minute 0.0.0.0:8081->80/tcp http [root@alph ~]# docker exec -it http /bin/bash root@2d7cc376dd27:/usr/local/apache2# ls #工作目录 bin build cgi-bin conf error htdocs icons include logs modules root@2d7cc376dd27:/usr/local/apache2# cd htdocs/ #容器文件目录 root@2d7cc376dd27:/usr/local/apache2/htdocs# ls index.html root@2d7cc376dd27:/usr/local/apache2/htdocs# echo " It is so beautiful!" >> inde.html
b)多次使用可以实现多个接口的映射
docker run -dti -p 5000:5000 -p 5022:22 centos:7.0 /bin/bash
c)映射到指定地址的指定接口
此时会绑定本地 192.168.4.169 接口上的 5000 到容器的 5000 接口
docker run -dti -p 192.168.4.169:5000:5000 centos:7.0 /bin/bash
d) 映射到指定地址的任意接口
此时会绑定本地 192.168.4.169 接口上的任意一个接口到容器的 5000 接口
docker run -dti -p 192.168.4.169::5000 centos:7.0 /bin/bash
e) 使用接口标记来指定接口的类型
docker run -dti -p 192.168.4.169::5000/UDP centos:7.0 /bin/bash
11) 通过端口映射实现访问本地的 IP:PORT 可以访问到容器内的 web
[root@alph ~]# for id in `docker ps -a | awk '{print $1}' | grep -v CONTAINER`;do docker rm -f $id;done [root@alph ~]# docker run -itd --name http reg.yunwei.edu/learn/httpd:latest 34099c67cf07685fa830c1feb143d2f948a5231a48d5d542a285d3cd62a074d4 [root@alph ~]# docker exec -it http /bin/bash root@34099c67cf07:/usr/local/apache2# ls bin build cgi-bin conf error htdocs icons include logs modules root@34099c67cf07:/usr/local/apache2# 将容器http的/usr/local/apache2导出以免丢失目录下内容 [root@alph ~]# docker cp http:/usr/local/apache2 ./ [root@alph ~]# ls anaconda-ks.cfg apache2 doc_file docker test [root@alph ~]# cd apache2/ [root@alph apache2]# ls bin build cgi-bin conf error htdocs icons include logs modules 将现在在root下的目录apache2映射给容器下的/usr/local/apache2 [root@alph ~]# docker run -itd -v /root/apache2/:/usr/local/apache2 -p 8081:80 --name http2 reg.yunwei.edu/learn/httpd 31ca9cce1b2c61043bfa385a1572bf9d1bf76fa19a45c8f7b2a63c983f9073a8 映射完成后相当于共享文件夹,在容器创建的文件在宿主机相应目录下能够查到,同样在宿主机相关文件进行的修改对容器有效 [root@alph ~]# docker exec -it http2 /bin/bash root@31ca9cce1b2c:/usr/local/apache2# ls bin build cgi-bin conf error htdocs icons include logs modules root@31ca9cce1b2c:/usr/local/apache2# touch aaaaa root@31ca9cce1b2c:/usr/local/apache2# exit exit [root@alph apache2]# ls aaaaa bin build cgi-bin conf error htdocs icons include logs modules [root@alph apache2]# cd htdocs/ [root@alph htdocs]# ls index.html [root@alph htdocs]# vim index.html <html><body><h1>It works!</h1></body></html> <html><body><h1>It so beautiful!</h1></body></html> 将该容器删除后其文件将不受影响,再次激活该容器该文件可以继续使用,这是一种动态的更改。