本文最后更新于 259 天前,其中的信息可能已经过时,如有错误请发送邮件到wuxianglongblog@163.com
docker的端口映射实战篇
前置知识
1.IP地址的分类
IP地址:
是在互联网上给主机编址的方式,为每个计算机分配一个逻辑地址,这样不但能够对计算机进行识别,还能进行信息共享。
网络地址(Network address)
则是互联网上的节点在网络中具有的逻辑地址,可对节点进行寻址。不可能变。
表示主机所属的网络 类似 送快递 所属的区域 北京 上海 深圳 山东
主机地址(Host address)
表示主机本身 类似 送快递 昌平区沙河科技园
IP地址分类:(5类)
A类地址:
(1)第1字节为网络地址,其它3个字节为主机地址;
(2)地址范围:1.0.0.1—126.155.255.254;
(3)10.X.X.X是私有地址,127.X.X.X是保留地址;
B类地址:
(1)第1字节和第2字节为网络地址,其它2个字节为主机地址
(2)地址范围:128.0.0.1—191.255.255.254
(3)172.16.0.0—172.31.255.255是私有地址,169.254.X.X是保留地址
C类地址:
(1)第1字节、第2字节和第3个字节为网络地址,第4个字节为主机地址
(2)地址范围:192.0.0.1—223.255.255.254
(3)192.168.X.X是私有地址
D类地址:(多播地址)
(1)不分网络地址和主机地址,它的第1个字节的前四位固定为1110
(2)地址范围:224.0.0.1—239.255.255.254
E类地址:(保留地址)
(1)不分网络地址和主机地址,第1个字节的前五位固定为11110
(2)地址范围:240.0.0.1—255.255.255.254
2.IPv4已被分配完毕怎么解决呢?
方案一:
使用IPv6解决。
方案二:
使用NAT技术。
方案三:
Ipv9等....
3.TCP报文
4.UDP报文
一.端口映射概述
1.什么是端口映射
端口映射是把外网IP地址的某一个端口映射到内网的某台主机的某台端口。
如下图所示就体现了端口映射的应用场景。
2.在VMware Workstation中配置端口映射
如下图所示,咱们的VMware Workstation也支持端口映射哟~
3.禁用内核转发参数(net.ipv4.ip_forward)
如下图所示,当我们禁用了内核转发参数(net.ipv4.ip_forward)启动容器会有WARNING信息提示哟~
温馨提示:
若禁用内核转发参数,则容器无法联网,也可借此机会讲解"--privileged"参数.
二.docker的端口映射原理
1.修改宿主机的网卡名称为eth0
具体步骤如下:
(1)编辑/etc/default/grub配置文件(或:修改/boot/grub2/grub.cfg),只需改动下面一行即可。
GRUB_CMDLINE_LINUX="... rhgb quiet net.ifnames=0"
(2)为grub2生成其配置文件
grub2-mkconfig -o /etc/grub2.cfg(该文件是一个软连接)
(3)修改网卡的配置文件哟~
[root@docker201.oldboyedu.com ~]# cd /etc/sysconfig/network-scripts/
[root@docker201.oldboyedu.com /etc/sysconfig/network-scripts]# mv ifcfg-ens33 ifcfg-eth0
[root@docker201.oldboyedu.com /etc/sysconfig/network-scripts]#
[root@docker201.oldboyedu.com /etc/sysconfig/network-scripts]# vim ifcfg-eth0
[root@docker201.oldboyedu.com /etc/sysconfig/network-scripts]#
[root@docker201.oldboyedu.com /etc/sysconfig/network-scripts]#
[root@docker201.oldboyedu.com /etc/sysconfig/network-scripts]# cat ifcfg-eth0
TYPE=Ethernet
BOOTPROTO=static
NAME=eth0
UUID=2e8e9fb2-eca7-43ce-bfcd-7663a6cfc0fc
DEVICE=eth0
ONBOOT=yes
IPADDR=172.200.1.201
NETMASK=255.255.248.0
GATEWAY=172.200.7.254
DNS1=172.200.7.254
DNS2=114.114.114.114
[root@docker201.oldboyedu.com /etc/sysconfig/network-scripts]#
(4)重启系统
[root@docker201.oldboyedu.com ~]# reboot
参考连接:
https://www.cnblogs.com/yinzhengjie/p/11878641.html
2.启动docker守护进程会多出一块网卡
如下图所示,当我们启动docker后,不难发现会多出来一块名为"docker0"的网卡。
3.启动容器后宿主机会多一块虚拟网卡设备
如下图所示,当我们启动一个容器时,虚拟机会多出来一块网卡哟~
4.docker容器的网络架构图
当我们在宿主机访问容器的服务时,docker网络的架构图大致如下图所示。
值得注意的是,我们可以执行"brctl show"命令查看当前主机的bridge(网桥)信息,也可以执行安装命令:
yum -y install bridge-utils
推荐阅读:
https://www.huweihuang.com/article/docker/docker-architecture/
温馨提示:
容器退出后,其占用的IP地址资源将会被释放哟~
5.课堂练习
随机启动一个nginx容器,请自行使用iptables实现服务访问。
参考案例:(本案例通过ss无法查看监听的端口)
(1)yum安装iptables
yum -y install iptables-services
(2)加载防火墙相关模块(可省略)
modprobe ip_tables
modprobe iptable_filter
modprobe iptable_nat
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp
modprobe ipt_state
(3)启动iptables
systemctl start iptables
(4)清空filter表的默认规则,避免实验干扰.(生产环境慎用,因为它可能会导致如下图所示的报错)
iptables -F
(5)编写iptables规则,实现NAT
iptables -t nat -A PREROUTING -d 192.168.15.101 -p tcp --dport 9999 -j DNAT --to-destination 172.17.0.2:80
(6)访问宿主机端口测试即可
http://192.168.15.101:9999/
6.启动容器时指定端口映射(背后会自动生成相应的iptables规则哟~)
[root@docker201.oldboyedu.com ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]# docker container run -it -d --name oldboyedu_nginx -p 8888:80 nginx:1.20.1
5e29a2c9d3abf041dfec14ed4179b841fe709f27b73a2cde4aa4e3edc8e8d76c
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5e29a2c9d3ab nginx:1.20.1 "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 0.0.0.0:8888->80/tcp, :::8888->80/tcp oldboyedu_nginx
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]# iptables -t nat -L -n -v
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
3 228 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8888 to:172.17.0.2:80
[root@docker201.oldboyedu.com ~]#
7.使用"-p"选项不仅仅是生成了iptables规则,还监听了相应的端口
[root@docker201.oldboyedu.com ~]# docker container run -it -d --name oldboyedu_nginx -p 8888:80 nginx:1.20.1
温馨提示:
当我们执行上述命令后,不仅仅会生成相应的iptables规则,还会使用docker-proxy进程来监听相应的端口。
8.监听相应的端口目的是为了防止重复配置端口映射信息
如下图所示,当我们已经为某个端口创建了端口映射后,再次配置相同的端口映射也会报错哟。
温馨提示:
如下图所示,我们也不能配置相同的容器名称哟~
三.docker常见的端口映射写法
1.绑定服务器的所有网卡("-p 服务器端口:容器端口"),最常用的写法
[root@docker201.oldboyedu.com ~]# docker container run -d -p 8888:80 nginx:1.20.1
2.绑定指定的网卡("-p 服务器网卡地址:服务器端口:容器端口")
[root@docker201.oldboyedu.com ~]# docker container run -d -p 127.0.0.1:8888:80 nginx:1.20.1
温馨提示:
如下图所示,我们可以基于指定的网卡来监听咱们的端口哟~
3.多个容器同时使用80端口案例
如上图所示,执行以下命令,我们可以创建一个子网卡用于测试(目的是模拟多块网卡,因为我的服务器就一块网卡):
[root@docker201.oldboyedu.com ~]# ifconfig eth0:1 172.200.1.210/21 up
如下图所示,根据实际的网卡地址,让多个容器使用指定的端口:
[root@docker201.oldboyedu.com ~]# docker run -d -p 172.200.1.201:80:80 nginx:1.20.1
80157eb8fbad112040adb8c463b2d24de203e7ff0df8bf6785ba69539372f4a5
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]# docker run -d -p 172.200.1.210:80:80 nginx:1.20.1
1b169b72c7118725f372fd9c8d6480bad42032c9cb322b46774d7634e796b6a6
[root@docker201.oldboyedu.com ~]#
4.使用宿主机的随机端口映射("-p 服务器网卡地址::容器端口")
[root@docker201.oldboyedu.com ~]# docker run -d -p 172.200.1.210::80 nginx:1.20.1
5.使用udp协议作为随机端口映射("-p 服务器网卡地址::容器端口/协议类型")
[root@docker201.oldboyedu.com ~]# docker run -d -p 172.200.1.210::80/udp nginx:1.20.1
如下图所示,我们在映射端口时可以指定协议,若不指定默认基于tcp协议进行映射的。
在实际工作中,很多服务都是基于udp的,比如DHCP,DNS(TCP/UDP的53d端口),chrony,SNMP(161端口)
6.暴露容器的多端口(多次使用"-p"参数即可)
[root@docker201.oldboyedu.com ~]# docker run -d -p 172.200.1.201:9200:9200 -p 172.200.1.201:9300:9300 nginx:1.20.1
如下图所示,我们可以给容器同时暴露多个端口哟~
温馨提示:
你是否发现我们启动容器时只暴露了该容器的9200和9300端口,为什么会多暴露出一个80端口呢?
请允许我先卖个关子,后面的会有讲解哟~
7.端口范围映射(了解即可)
[root@docker201.oldboyedu.com ~]# docker run -d -p 666-670:886-890 nginx:1.20.1
如下图所示,如果有需要的话,我们可以基于范围的端口映射,但这种场景通常很少用。
8.自动随机端口映射("-P",大写的字母"P")
[root@docker201.oldboyedu.com ~]# docker run -d -P nginx:1.20.1
温馨提示:
如下图所示,很多容器是不支持端口映射的哟~后面的课程会讲解什么样的镜像支持自动随机端口映射。
四.可能会遇到的报错
1.iptables: No chain/target/match by that name
报错原因:
课堂练习是否使用"iptables -F"手动清空了docker相关的自定义链表.
解决方案:
重启docker服务。
2. Bind for 0.0.0.0:8888 failed: port is already allocated.
报错原因:
端口已被占用。
解决方案:
换个宿主机端口映射即可。