007、docker的端口映射实战篇
本文最后更新于 257 天前,其中的信息可能已经过时,如有错误请发送邮件到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

image-20210702150100539

2.IPv4已被分配完毕怎么解决呢?

方案一:
    使用IPv6解决。

方案二:
    使用NAT技术。

方案三:
    Ipv9等....

3.TCP报文

image-20210702163828510

4.UDP报文

image-20210702164124494

一.端口映射概述

1.什么是端口映射

    端口映射是把外网IP地址的某一个端口映射到内网的某台主机的某台端口。

    如下图所示就体现了端口映射的应用场景。

image-20210612205900888

2.在VMware Workstation中配置端口映射

    如下图所示,咱们的VMware Workstation也支持端口映射哟~

image-20210612211239149

3.禁用内核转发参数(net.ipv4.ip_forward)

    如下图所示,当我们禁用了内核转发参数(net.ipv4.ip_forward)启动容器会有WARNING信息提示哟~

    温馨提示:
        若禁用内核转发参数,则容器无法联网,也可借此机会讲解"--privileged"参数.

image-20210612213129061

二.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

image-20210612220741564

2.启动docker守护进程会多出一块网卡

如下图所示,当我们启动docker后,不难发现会多出来一块名为"docker0"的网卡。

image-20210612221706804

3.启动容器后宿主机会多一块虚拟网卡设备

如下图所示,当我们启动一个容器时,虚拟机会多出来一块网卡哟~

image-20210612223715401

4.docker容器的网络架构图

当我们在宿主机访问容器的服务时,docker网络的架构图大致如下图所示。

值得注意的是,我们可以执行"brctl show"命令查看当前主机的bridge(网桥)信息,也可以执行安装命令:
    yum -y install bridge-utils

推荐阅读:
    https://www.huweihuang.com/article/docker/docker-architecture/

温馨提示:
    容器退出后,其占用的IP地址资源将会被释放哟~

image-20210612234102226

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/

1629255913851

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 ~]# 

image-20210612235313951

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进程来监听相应的端口。

image-20210613000129839

8.监听相应的端口目的是为了防止重复配置端口映射信息

    如下图所示,当我们已经为某个端口创建了端口映射后,再次配置相同的端口映射也会报错哟。

    温馨提示:
        如下图所示,我们也不能配置相同的容器名称哟~

image-20210613000938313

三.docker常见的端口映射写法

1.绑定服务器的所有网卡("-p 服务器端口:容器端口"),最常用的写法

[root@docker201.oldboyedu.com ~]# docker container run -d -p 8888:80 nginx:1.20.1

image-20210613002009459

2.绑定指定的网卡("-p 服务器网卡地址:服务器端口:容器端口")

[root@docker201.oldboyedu.com ~]# docker container run -d -p 127.0.0.1:8888:80 nginx:1.20.1

温馨提示:
    如下图所示,我们可以基于指定的网卡来监听咱们的端口哟~

image-20210613002621180

3.多个容器同时使用80端口案例

image-20210613004906493

    如上图所示,执行以下命令,我们可以创建一个子网卡用于测试(目的是模拟多块网卡,因为我的服务器就一块网卡):
        [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 ~]# 

image-20210613005330982

4.使用宿主机的随机端口映射("-p 服务器网卡地址::容器端口")

[root@docker201.oldboyedu.com ~]# docker run -d -p 172.200.1.210::80 nginx:1.20.1

image-20210613010351889

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端口)

image-20210613010823008

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端口呢?
    请允许我先卖个关子,后面的会有讲解哟~

image-20210613011920434

7.端口范围映射(了解即可)

    [root@docker201.oldboyedu.com ~]# docker run -d -p 666-670:886-890 nginx:1.20.1

    如下图所示,如果有需要的话,我们可以基于范围的端口映射,但这种场景通常很少用。

image-20210613012610158

8.自动随机端口映射("-P",大写的字母"P")

[root@docker201.oldboyedu.com ~]# docker run -d -P nginx:1.20.1 

温馨提示:
    如下图所示,很多容器是不支持端口映射的哟~后面的课程会讲解什么样的镜像支持自动随机端口映射。

image-20210613013116889

四.可能会遇到的报错

1.iptables: No chain/target/match by that name

报错原因:
    课堂练习是否使用"iptables -F"手动清空了docker相关的自定义链表.

解决方案:
    重启docker服务。

1629255977678

2. Bind for 0.0.0.0:8888 failed: port is already allocated.

报错原因:
    端口已被占用。

解决方案:
    换个宿主机端口映射即可。

1629256276788

谨此笔记,记录过往。凭君阅览,如能收益,莫大奢望。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇