默认情况下,容器使用的ip是172.17.0.0/16网段的,外界的用户只能访问宿主机的192.168.32.0/24网段,无法访问172.17.0.0/16网段。我们运行容器的目的:是希望运行在容器中的服务,能够被外界访问,这里就涉及到了外网192.168.32.0/24到容器内网172.17.0.0/16网段的转换,所以需要做端口映射。

二、docker运行容器端口映射的方法

指定映射(docker 自动添加一条iptables规则实现端口映射)
-p hostPort:containerPort
-p ip:hostPort:containerPort 
-p ip::containerPort(随机端口)
-p hostPort:containerPort:udp
-p 81:80 -p 443:443 可以指定多个-p

随机映射
docker run -P (随机端口)

iptables
[root@inode3 ~]# iptables -t nat -L -n
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           
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           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:80 to:172.17.0.2:80
#容器172.17.0.2的tcp80端口已经映射到了外网的80端口上

三、docker容器的四种网络模式

1、容器网络配置命令

docker run --name 运行的容器名称 --net=网络参数选项 -p 容器端口映射 镜像名称:镜像版本

--net=网络参数选项

None:不为容器配置任何网络功能,--net=none

Container:与另一个运行中的容器共享Network Namespace,--net=container:containerID

Host:与主机共享Network Namespace,--net=host

Bridge:Docker设计的NAT网络模型

docker网络查看命令

[root@inode4 ~]#docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
a736b9bf0850        bridge              bridge              local
db0ed8b2be23        host                host                local
0339ee737df3        mac1                macvlan             local
90c917be552d        none                null                local

2、容器的四种网络模式

docker容器的网络通信原理:

1、 当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上,所以有默认地址172.17.0.0/16的地址。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

[root@inode4 ~]# ifconfig docker0
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:8cff:fe57:ebf8  prefixlen 64  scopeid 0x20<link>
    ether 02:42:8c:57:eb:f8  txqueuelen 0  (Ethernet)
    RX packets 194130  bytes 20622371 (19.6 MiB)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 250033  bytes 780264041 (744.1 MiB)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

2、 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。

yum install -y bridge-utils-1.5-9.el7.x86_64
[root@inode4 ~]# brctl show
bridge name    bridge id        STP enabled    interfaces
docker0        8000.02428c57ebf8    no        veth16bb7cf #宿主机中docker0的网卡
                                        vethccb0469 #容器的网卡(在容器中eth0)

第一种网络模式:Bridge(docker默认的网络模式)

bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。

[root@inode3 ~]# iptables -t nat -L -n
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           
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           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:80 to:172.17.0.2:80
#容器172.17.0.2的tcp80端口已经映射到了外网的80端口上

docker bridge原理图

五、docker容器的网络访问

bridge案例

[root@inode3 ~]# docker run --net=bridge -it centos:6.9 /bin/bash
[root@b796f4521c28 /]# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:03  
      inet addr:172.17.0.3  Bcast:172.17.255.255  Mask:255.255.0.0
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:6 errors:0 dropped:0 overruns:0 frame:0
      TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0 
      RX bytes:508 (508.0 b)  TX bytes:0 (0.0 b)

[root@b796f4521c28 /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
 0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
 172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

第二种模式:Host

如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

docker host原理图

五、docker容器的网络访问

 

host案例

[root@inode3 ~]# docker run -it --net=host centos:6.9 /bin/bash
[root@inode3 /]# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:0C:29:E2:7B:77  
      inet addr:192.168.32.103  Bcast:192.168.32.255  Mask:255.255.255.0
      inet6 addr: fe80::dceb:89ad:3d37:bebe/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:603672 errors:361 dropped:444 overruns:0 frame:0
      TX packets:245020 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1000 
      RX bytes:795145514 (758.3 MiB)  TX bytes:20746259 (19.7 MiB)

发现ip与宿主机的ip一样

第三种模式:Container 网络模式

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

docker container原理图

五、docker容器的网络访问

 

命令格式

docker run --name 运行容器名称 -d -p 容器的端口影身 --network container:共享网络的容器名 镜像:镜像版本

container案例

现有运行容器web1

[root@inode3 ~]# docker inspect web1 |grep -i "ipaddress"
        "SecondaryIPAddresses": null,
        "IPAddress": "172.17.0.2",
                "IPAddress": "172.17.0.2",

运行一个新的容器centos6.9,网络与容器web1共享

 

[root@inode3 ~]# docker run -it --name centos6.9 --network container:web1 centos:6.9
[root@7c5d1590be34 /]# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
      inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:17 errors:0 dropped:0 overruns:0 frame:0
      TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0 
      RX bytes:1280 (1.2 KiB)  TX bytes:1272 (1.2 KiB)

新运行的容器centos6.9的ip已经与容器web1共享,他们的文件系统是不共享 在容器centos6.9的/tmp目录下创建一个ywx.log文件

[root@7c5d1590be34 tmp]# touch ywx.log
[root@7c5d1590be34 tmp]# ls
anaconda-post.log  yum.log  ywx.log

查看容器web1的/tmp目录 [root@inode3 ~]# docker exec -it web1 /bin/bash root@7c5d1590be34:/# ls /tmp

第四种模式:none

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息,只有lo 网络接口。需要我们自己为Docker容器添加网卡、配置IP等。

不参与网络通信,运行于此类容器中的进程仅能访问本地回环接口;仅适用于进程无须网络通信的场景中,例如:备份、进程诊断及各种离线任务等。

docker none原理图

五、docker容器的网络访问

 

none案例

 

[root@inode3 ~]# docker run -it --name centos6.9 --network none centos:6.9 /bin/bash
[root@9703a325d77f /]# ifconfig eth0
eth0: error fetching interface information: Device not found
[root@9703a325d77f /]# ifconfig     
lo        Link encap:Local Loopback  
      inet addr:127.0.0.1  Mask:255.0.0.0
      UP LOOPBACK RUNNING  MTU:65536  Metric:1
      RX packets:0 errors:0 dropped:0 overruns:0 frame:0
      TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1000 
      RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)