Docker–网络详解
容器网络实质上是由Docker为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作系统的网络环境中独立出来,形成容器自有的网络设备、IP 协议栈、端口套接字、IP 路由表、防火墙等与网络相关的模块。
Docker网络原理
Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP, 同时Docker网桥是 每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信
[root@localhost ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:b1:c5:3b:4f txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
容器内先安装net-tools工具yum install -y net-tools然后查看容器IP(container ip)
[root@localhost ~]# yum install -y net-tools
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2d1f43c3d536 tomcat:latest "/bin/bash" 6 seconds ago Created reverent_banzai
#使用大写p进行随机端口映射
[root@localhost ~]# docker run -itd --name test1 -P tomcat
95fffcb47dbbd93ed798ada33a54b2aa5b17d8fb1e4a7ab73fb638501ca54a5b
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
95fffcb47dbb tomcat "catalina.sh run" 5 seconds ago Up 4 seconds 0.0.0.0:49153->8080/tcp, :::49153->8080/tcp test1
2d1f43c3d536 tomcat:latest "/bin/bash" 2 minutes ago Exited (137) About a minute ago reverent_banzai
#使用小写p加端口进行指定的端口映射
[root@localhost ~]# docker run -itd --name test2 -p 49110:80 tomcat
581f77fc4c7cd42d2c41bd9126d9ff0226583e3368d8366dedb1a56e4417a389
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
581f77fc4c7c tomcat "catalina.sh run" 3 seconds ago Up 2 seconds 8080/tcp, 0.0.0.0:49110->80/tcp, :::49110->80/tcp test2
95fffcb47dbb tomcat "catalina.sh run" 2 minutes ago Up 2 minutes 0.0.0.0:49153->8080/tcp, :::49153->8080/tcp test1
2d1f43c3d536 tomcat:latest "/bin/bash" 4 minutes ago Exited (137) 3 minutes ago reverent_banzai
#测试
分别登录192.168.237.141:49110和192.168.237.141:49153可以访问tomcat页面
#可以访问是因为通过iptables的DNAT进行了转换
[root@localhost ~]# iptables -nL -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
RETURN all -- 192.168.122.0/24 224.0.0.0/24
RETURN all -- 192.168.122.0/24 255.255.255.255
MASQUERADE tcp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
MASQUERADE udp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
MASQUERADE all -- 192.168.122.0/24 !192.168.122.0/24
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:8080
MASQUERADE tcp -- 172.17.0.3 172.17.0.3 tcp dpt:80
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49153 to:172.17.0.2:8080
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49110 to:172.17.0.3:80
默认网络
当你安装Docker时,它会自动创建三个网络。你可以使用以下docker network ls命令列出这些网络
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
69b39f1a9e1a bridge bridge local
da57f14ea87a host host local
b3681285c530 none null local
Docker网络类型
网络类型 | 描述 |
---|---|
Host | 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口 |
Container | 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围 |
None | 该模式关闭了容器的网络功能 |
Bridge | 默认为该模式,此模式会为每一个 容器分配、设置IP等,并将容器连接到一个docker0虛拟网桥,通过docker0网桥以及iptables nat表配置与宿主机通信 |
自定义网络模式 | 安装Docker时,它会自动创建三个网络,bridge (创建容器默认连接到此网络)、none 、host |
- 使用docker run 创建Docker容器时,可以用–net或–network 选项指定容器的网络模式
网络类型 | 描述 |
---|---|
host模式 | 使用–net=host指定 |
Noner模式 | 使用–net=none 指定 |
Container模式 | 使用–net=container:NAME_ _or_ID指定 |
Bridge模式 | 使用–net=bridge指定,默认设置,可省略 |
Host模式
Host 模式并没有为容器创建一个隔离的网络环境。而之所以称之为host模式,是因为该模式下的 Docker 容器会和 host 宿主机共享同一个网络 namespace,故 Docker Container可以和宿主机一样,使用宿主机的eth0,实现和外界的通信。换言之,Docker Container的 IP 地址即为宿主机 eth0 的 IP 地址,其特点包括:
- 这种模式下的容器没有隔离的 network namespace
- 容器的 IP 地址同 Docker host 的 IP 地址
- 需要注意容器中服务的端口号不能与 Docker host 上已经使用的端口号相冲突
- host 模式能够和其它模式共存
container模式
Container 网络模式是 Docker 中一种较为特别的网络的模式。处于这个模式下的 Docker 容器会共享其他容器的网络环境,因此,至少这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的容器存在网络隔离
[root@localhost ~]# docker inspect -f '{{.State.Pid}}' 95fffcb47dbb #查看容器进程PID
5996
[root@localhost ~]# ls -l /proc/5996/ns
总用量 0
lrwxrwxrwx. 1 root root 0 6月 24 19:58 ipc -> ipc:[4026532623]
lrwxrwxrwx. 1 root root 0 6月 24 19:58 mnt -> mnt:[4026532621]
lrwxrwxrwx. 1 root root 0 6月 24 19:38 net -> net:[4026532626] #查看container模式的Network Namespace
lrwxrwxrwx. 1 root root 0 6月 24 19:58 pid -> pid:[4026532624]
lrwxrwxrwx. 1 root root 0 6月 24 19:58 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 6月 24 19:58 uts -> uts:[4026532622]
[root@localhost ~]# docker run -itd --name test4 --net=container:95fffcb47dbb centos bash
590162d14ba58f544969ab80754389f6667799f27e92b276013f6cc83b71907f
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
590162d14ba5 centos "bash" 27 seconds ago Up 26 seconds test4
431ecd6d0eec tomcat "bash" 5 minutes ago Up 5 minutes test3
581f77fc4c7c tomcat "catalina.sh run" 25 minutes ago Up 25 minutes 8080/tcp, 0.0.0.0:49110->80/tcp, :::49110->80/tcp test2
95fffcb47dbb tomcat "catalina.sh run" 27 minutes ago Up 27 minutes 0.0.0.0:49153->8080/tcp, :::49153->8080/tcp test1
2d1f43c3d536 tomcat:latest "/bin/bash" 30 minutes ago Exited (137) 29 minutes ago reverent_banzai
[root@localhost ~]# docker inspect -f '{{.State.Pid}}' 590162d14ba5
6713
[root@localhost ~]# ls -l /proc/6713/ns
总用量 0
lrwxrwxrwx. 1 root root 0 6月 24 20:06 ipc -> ipc:[4026532845]
lrwxrwxrwx. 1 root root 0 6月 24 20:06 mnt -> mnt:[4026532843]
lrwxrwxrwx. 1 root root 0 6月 24 20:06 net -> net:[4026532626] #container模式的Network Namespace和上面的一致
lrwxrwxrwx. 1 root root 0 6月 24 20:06 pid -> pid:[4026532846]
lrwxrwxrwx. 1 root root 0 6月 24 20:06 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 6月 24 20:06 uts -> uts:[4026532844]
none模式
网络模式为 none,即不为 Docker 容器构造任何网络环境。一旦Docker 容器采用了none 网络模式,那么容器内部就只能使用loopback网络设备,不会再有其他的网络资源。Docker Container的none网络模式意味着不给该容器创建任何网络环境,容器只能使用127.0.0.1的本机网络
bridge模式
Docker 容器默认使用 bridge 模式的网络。其特点如下:
- 使用一个 linux bridge,默认为 docker0
- 使用 veth 对,一头在容器的网络 namespace 中,一头在 docker0 上
- 该模式下Docker Container不具有一个公有IP,因为宿主机的IP地址与veth pair的 IP地址不在同一个网段内
- Docker采用 NAT 方式,将容器内部的服务监听的端口与宿主机的某一个端口port 进行“绑定”,使得宿主机以外的世界可以主动将网络报文发送至容器内部
- 外界访问容器内的服务时,需要访问宿主机的 IP 以及宿主机的端口 port
- NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率
- 容器拥有独立、隔离的网络栈;让容器和宿主机以外的世界通过NAT建立通信
自定义网络模式创建步骤
创建自定义网络docker1
[root@localhost ~]# docker network create --subnet=172.18.0.0/16 --opt "com.docker.network.bridge.name"="docker1" mynetwork
dc47693a08090ecfbccdfef829aad2dfe1e6104dbe35f663935c0b3937e39d25
[root@localhost ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:b1ff:fec5:3b4f prefixlen 64 scopeid 0x20<link>
ether 02:42:b1:c5:3b:4f txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 12 bytes 1668 (1.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:94:ae:e6:48 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 指定IP运行docker
[root@localhost ~]# docker run -it --name test7 --net mynetwork --ip 172.18.0.15 centos:7 /bin/bash
[root@228a9b43ff7b /]# yum install net-tools
[root@228a9b43ff7b /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.18.0.15 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:ac:12:00:0f txqueuelen 0 (Ethernet)
RX packets 2895 bytes 23643460 (22.5 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2007 bytes 111783 (109.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0