docker互联三 网络
一、网络机制的五中类型
docker的网络模式大致可以分成五种类型,在安装完docker之后,宿主机上会创建三个网络,分别是bridge网络,host网络,none网络,可以使用docker network ls命令查看。
1.1、none网络
2.2、host网络
通过命令--network=host指定,使用host模式的容器可以直接使用docker host的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
1.3、bridge网络
开始docker0上没有任何网络设备,
创建一个容器之后一个新的网络接口被挂载到了docker0上,这个就是容器创建时创建的虚拟网卡。bridge模式为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,使容器之间,容器和docker host之间实现网络隔离。
通过Iptables实现容器内访问外部网络:
[root@localhost ~]# iptables-save |grep 172.17.0.* -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE -A FORWARD -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
1.4、container模式
创建容器时使用--network=container:NAME_or_ID这个模式在创建新的容器的时候指定容器的网络和一个已经存在的容器共享一个Network Namespace,但是并不为docker容器进行任何网络配置,这个docker容器没有网卡、IP、路由等信息,需要手动的去为docker容器添加网卡、配置IP等。
1.5、user-defined模式
用户自定义模式主要可选的有三种网络驱动:bridge、overlay、macvlan。bridge驱动用于创建类似于前面提到的bridge网络;overlay和macvlan驱动用于创建跨主机的网络。
二、实例解析
2.1、给自己的docker (Dcoker1.12GA)容器起个名称
给docker名称的好处是:
- 容易记
- 可以通过特殊命令,使得名称可以在容器和容器之间使用
2.1.1、查看docker已经存在的镜像
wxl@wxl-pc:~$ docker images
2.1.2、选择training/webapp这个镜像,通过–name命令设置名称
wxl@wxl-pc:~$ docker run -d -P --name wangxiaoleiweb training/webapp python app.py
最后一行可以看到wangxiaoleiweb已经命名成功
可以使用docker inspect通过刚刚设置的名称来查看wangxiaoleiweb
wxl@wxl-pc:~$ docker inspect wangxiaoleiweb
2.1.3、删除docker名称,docker的名称都是唯一的,即一但使用了就不能在另一个镜像使用该名称,可以删除后重新命名.(只删除名字,镜像不会被删除)
#停止运行中的镜像 wxl@wxl-pc:~$ docker stop wangxiaoleiweb #删除自定义的名称 docker rm wangxiaoleiweb web wxl@wxl-pc:~$ docker rm web web wxl@wxl-pc:~$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 50dae1ee8677 2 weeks ago 196.7 MB hello-world latest c54a2cc56cbb 4 weeks ago 1.848 kB training/webapp latest 6fae60ef3446 14 months ago 348.8 MB training/sinatra latest 49d952a36c58 2 years ago 447 MB
2.2、默认的容器的网络
2.2.1、Docker通过网络驱动(network driver),默认网络驱动分别是桥接(bridge)和覆盖(overlay)两种.
#查看Docker默认的三种网络 wxl@wxl-pc:~$ docker network ls NETWORK ID NAME DRIVER SCOPE 7f6b9cbd3eec bridge bridge local 0cb106f52e66 host host local cfb50541161b none null local
为一个容器桥接网络
wxl@wxl-pc:~$ docker run -itd --name=networktest ubuntu:14.04 2a433c9467d3d35474daa544dcac665ecc4b71b202b82d0bd59049f7d52e397f
wxl@wxl-pc:~$ docker network inspect bridge [ { "Name": "bridge", "Id": "7f6b9cbd3eece7301d196363b5250c44fd0b275f3c3d38a952af2ad8b2fd38c2", "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, "Containers": { "2a433c9467d3d35474daa544dcac665ecc4b71b202b82d0bd59049f7d52e397f": { "Name": "networktest", "EndpointID": "d0b94ec934b390784faa5ad8946e9ba6031afe4467889e1f7fe0eda5d79deac1", "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": {} } ]
可以看到通过检查网络可以看到容器的IP地址,名称等信息.
2.2.2、从网络中删除某个容器,可以通过该容器的网络名称,容器名称,id来作为删除的标示,但是通过网络名称是方便的,如networktest
wxl@wxl-pc:~$ docker network disconnect bridge networktest
再用docker network inspect bridge
会发现已经没有networktest信息了
2.3、自定义容器的网络
容器的网络(network)是用来隔离容器和容器之间或者网络与网络之间的方法,所以,所以我们通过建立网络来隔离容器.其中,内置的bridge网络是无法删除的.
2.3.1.创建网络
Docker Engine 支持两种网络桥接网络(bridge network)和覆盖网络(overlay network),桥接的网络局限于单个主机运行的Docker Engine,而覆盖网络可以包含多个主机.
wxl@wxl-pc:~$ docker network create -d bridge my-bridge-network
3bfde1ba62a75e38236517f4f0731f48c281cec107e976039773be134968c453
2.3.2、将一个容器添加至新创建的网络中
#这里创建了一个db的容器(若本地没有该镜像会自动拉取)
wxl@wxl-pc:~$ docker run -d --network=my-bridge-network --name db training/postgres
通过inspect命令查看已经添加至网络的db容器
wxl@wxl-pc:~$ docker inspect --format='{{json .NetworkSettings.Networks}}' db {"my-bridge-network":{"IPAMConfig":null,"Links":null,"Aliases":["237e0f7060b6"],"NetworkID":"3bfde1ba62a75e38236517f4f0731f48c281cec107e976039773be134968c453","EndpointID":"33516faca38c0f76bd2c6ebb6e8c2574c62e242d5a0c10b77c49e14b2549f3e5","Gateway":"172.18.0.1","IPAddress":"172.18.0.2","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:12:00:02"}}
2.3.3、通过ping的方式验证网络连通性,将两个容器(db容器和web容器)从不同的网络,放置同一个网络.
2.3.3.1、把training/webapp容器命名为web,方便后续操作
wxl@wxl-pc:~$ docker run -d --name web training/webapp python app.py
8f12cfaaedda2b348bef437fa2eeed19ef69ad07cd98aa72e0c2113710413e6f
2.3.3.2、查看web容器的ip
wxl@wxl-pc:~$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web 172.17.0.2
2.3.3.3、进入db容器并且尝试ping一下web容器,发现是ping不通,ctrl+c终止ping,如下图
#进入db容器 wxl@wxl-pc:~$ docker exec -it db bash #首次尝试ping web容器 root@237e0f7060b6:/# ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. ^C --- 172.17.0.2 ping statistics --- 24 packets transmitted, 0 received, 100% packet loss, time 23183ms root@237e0f7060b6:/# exit
2.3.3.4、现在,将web容器添加至db容器的网络(即my-bridge-network),然后在ping,即可ping通
wxl@wxl-pc:~$ docker network connect my-bridge-network web
#再次进入db容器 wxl@wxl-pc:~$ docker exec -it db bash #ping web容器,发现已经可以ping通 root@237e0f7060b6:/# ping web PING web (172.18.0.3) 56(84) bytes of data. 64 bytes from web.my-bridge-network (172.18.0.3): icmp_seq=1 ttl=64 time=0.097 ms 64 bytes from web.my-bridge-network (172.18.0.3): icmp_seq=2 ttl=64 time=0.110 ms 64 bytes from web.my-bridge-network (172.18.0.3): icmp_seq=3 ttl=64 time=0.109 ms ^C --- web ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1998ms rtt min/avg/max/mdev = 0.097/0.105/0.110/0.010 ms
可见,不同的容器在不同的网络是可以起到隔离作用的,所以,自定义一个网络可以保证容器和容器之间通信安全