Docker 学习笔记 - 网络的端口映射

当我们在Docker的宿主机里面启动Docker的时候,他们之间是可以互相通信的,那么外界是如何访问容器的呢?
看看下面这张简图

Docker 学习笔记 - 网络的端口映射

宿主机上的真正网卡是eth0,他的IP是 10.0.0.11, 当我们配置了docker之后,他会自动生成一个虚拟的网卡 docker0, IP是 172.17.0.1,这个子网是docker容器之间通讯的子网,所有的docker容器会自动生成一个vethxxx的虚拟网卡,IP地址都是172.17.0.0/24这个范围,他们之间通过一个 docker0的网桥虚拟机进行联系。那么外界如何来访问172.17.0.0/24这个内网系统呢? 我们通过DNAT 端口映射来实现。他会把eth0的宿主机的IP和端口和 对应的容器的IP和端口进行映射。 这个映射是通过Linux的防火墙iptables来实现的,不过我们不需要手动配置,而是在启动run命令 的时候用-p选项指定即可

ifconfig查看网卡

[root@ip-172-16-1-150 ec2-user]# docker run -d -p 8000:80 nginx
6bf871a60c8110f3389db0a02a5ff45f8713c157f9cb5fa946e40638acf494a3
[root@ip-172-16-1-150 ec2-user]# 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:4cff:feff:2845  prefixlen 64  scopeid 0x20<link>
        ether 02:42:4c:ff:28:45  txqueuelen 0  (Ethernet)
        RX packets 1277  bytes 1107179 (1.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1573  bytes 9220451 (8.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 172.16.1.150  netmask 255.255.255.0  broadcast 172.16.1.255
        inet6 fe80::8a6:48ff:fe3f:cff2  prefixlen 64  scopeid 0x20<link>
        ether 0a:a6:48:3f:cf:f2  txqueuelen 1000  (Ethernet)
        RX packets 122949  bytes 42060109 (40.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 95494  bytes 10487762 (10.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        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

veth63254cc: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::94ca:c5ff:fe3a:cb4c  prefixlen 64  scopeid 0x20<link>
        ether 96:ca:c5:3a:cb:4c  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 696 (696.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

iptable自动配置端口转发的规则


[root@ip-172-16-1-150 ec2-user]# 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 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 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 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:8000 to:172.17.0.2:80

下面看个简单的实例

我的宿主机是一个AWS 的EC2 实例,作为测试,我分配了两个private IP地址给这个服务器,分别是172.16.1.150和 172.16.1.120

Docker 学习笔记 - 网络的端口映射

然后我给eth0 网卡分配一个新的IP地址

ifconfig eth0:0 add 172.16.1.120/24 up

这样我可以通过两个IP来访问不同的容器。


[root@ip-172-16-1-150 ec2-user]# docker run -d -p 172.16.1.120:80:80 nginx
3c2fe5b1f1e78abc522417bc05668317d18f7e18ba3779e06777238438c1210c
[root@ip-172-16-1-150 ec2-user]# docker run -d -p 172.16.1.150:80:80 ghost:alpine
97782eed76f0b50de459dd3789e58155bd600138dc3d1c433567bcceea310c87
[root@ip-172-16-1-150 ec2-user]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
97782eed76f0        ghost:alpine        "docker-entrypoint.s…"   7 seconds ago       Up 6 seconds        172.16.1.150:80->80/tcp, 2368/tcp   festive_hermann
3c2fe5b1f1e7        nginx               "/docker-entrypoint.…"   20 seconds ago      Up 19 seconds       172.16.1.120:80->80/tcp             laughing_kalam
[root@ip-172-16-1-150 ec2-user]#    

测试一下, 成功

Docker 学习笔记 - 网络的端口映射

Docker 学习笔记 - 网络的端口映射

上一篇:5.写一个sh脚本,可以通过一台机器控制多台机器


下一篇:rhel 6 虚拟机连接互联网