iptables实现docker容器动态端口映射实操

2024-04-24 14:28

本文主要是介绍iptables实现docker容器动态端口映射实操,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

之前在《Docker 动态修改容器端口映射的方法》一文中,说明了如何使用修改配置和加防火墙规则实现动态端口映射。但是没有具体分享加防火墙实现动态端口映射的实际案例。今天就分享一下实际操作案例,供大家参考。

分析

动态端口映射的用途

容器端口的动态映射,是用于实现外部访问服务器上的容器内运行的服务的。

如果容器已经运行了,不想停止Docker服务,又想增加端口映射,以便让外部可以立即访问,那就需要使用iptables来实现端口的动态映射。如果可以重启Docker服务,那么采用前面的文章里的方法即可。

实践操作的环境

宿主机局域网IP:192.168.1.15

容器的IP:172.17.0.2

容器已映射端口:443

容器内有监听0.0.0.0的端口:8086

容器内是否开启防火墙:没有开启

宿主机是否正常访问容器的端口:是

宿主机是否开启IPv4转发:是

宿主机局域网IP查看:

ip addr

找到eth0即宿主机使用的网卡这一组,可以看到。

容器IP查看:

docker exec {容器名或容器ID} ip addr

找到eth0@ifxxx这样的一组,查看对应的IP。一般是172开头的,默认一般是172.17.0.2。

容器已有的端口映射查看:

docker ps

找到容器名那一行,找到PORTS那一列,就是已经做好的端口映射。例如:0.0.0.0:443->443/tcp 。

查看容器内已监听的端口:

docker exec {容器名或容器ID} netstat -ltnp|grep 0.0.0.0|grep -v 127.0.0.1

这里过滤出来监听0.0.0.0的端口并排除监听127.0.0.1的端口。选择一个没有做端口映射的来作为测试,我们这里选择的是8086。

查看容器是否开启防火墙:

docker exec {容器名或容器ID} service iptables status | grep Active

如果不是running状态,即没有运行。

因为我移除了iptbales服务配置文件,容器内的防火墙是没有起来的。

查看宿主机是否正常telnet访问容器的8086端口:

如上图所示,看到了Escape character is '^]'即表示端口是通的,可以正常访问,如果没有出现则表示不通。

查看宿主机是否开启IPv4转发:

sysctl net.ipv4.ip_forward

如果返回的值为1即表示开启了,值为0表示未开启。

可以看到,已经开启了IPv4的转发。

实践操作目标

我们使用iptables添加规则,实现在不重启Docker服务和容器的前提下,让外部可以访问容器里的8086服务,即可以telnet宿主机192.168.1.15的8086端口。

实践步骤

1.测试宿主机IP是否可以telnet 连接192.168.1.15 的8086

可以发现:

Trying 192.168.1.15...
telnet: connect to address 192.168.1.15: Connection refused

因为本机并没有监听8086端口,所以使用本机无法telnet8086端口。那从外部执行本机的8086就更不可能成功了。此时我们就是无法从外部访问容器的8086端口的。

2.设置根据端口的转发

只要宿主机IP接收到8086的端口的请求,就转发到172.17.0.2上的8086。前面我们已经确认了172.17.0.2的8086端口是可以通信的。所以请求只要转发到172.17.0.2的8086,请求就可以进入容器。

iptables -t nat -A DOCKER -p tcp --dport {容器外部端口} -j DNAT --to-dest {容器ip}:{容器内部端口}

-t nat:用于指定在nat表添加规则。NAT表用于做IP和端口转换的。

-p tcp:用于指定转换的协议为tcp,这个根据监听的协议来填写。

-A DOCKER:在DOCKER链追加一条规则。如果要把规则写到最开始即最优先匹配,可以把A换成I。A即add,追加到末尾,I即insert,插入到开头。

--dport即容器外部的端口,也即宿主机的端口。这里我们替换为8086。

-j DNAT:就是做DNAT的转换,把目的IP和端口进行转换。

--to-dest:将请求的目的IP和端口修改为什么。这里换为容器的IP和容器内监听的8086。

容器外部的端口和容器内部的端口可以不一样,但是容器内部的端口必须是内部已经监听的端口,而容器外部的端口就是外部拿来通信的端口。

最终的命令如下:

iptables -t nat -A DOCKER -p tcp --dport 8086 -j DNAT --to-dest 172.17.0.2:8086

执行后查看iptables的nat表:

iptables -t nat -nL DOCKER | grep 8086

在宿主机上试一下telnet就通了。

这样就搞定了吗?你从局域网的其他机器执行telnet 192.168.1.15 8086,发现还是不通。

到此,我们已经打通了宿主机可以通过宿主机IP对端口的直接访问,但是外部的还不行。如果你只是需要宿主机可以访问,那就到此结束了。如果你需要在局域网的其他机器也能访问,那还要继续。

3.添加允许外部IP访问8086端口的规则

iptables -A DOCKER -p tcp -s {外部IP} --dport {宿主机的端口} -j ACCEPT

默认不加-t参数,默认就是filter表。-s(源IP)参数用于指定外部特定IP允许访问宿主机。如果不加-s表示外部所有IP都可以访问。--dport则表示只能访问指定的端口。-j ACCEPT表示允许。

最终的命令如下:

iptables -A DOCKER -p tcp -s 外部IP --dport 8086 -j ACCEPT

不过你会发现,此时还是无法从外部IP访问8086。此时虽然外部能请求到宿主机的8086,但是宿主机将这个请求丢了。在宿主机上请求,因为都是内部IP,不管是用宿主机的局域网IP还是172的,都是内部流量,所以会通过容器的网桥进行转发,所以宿主机上可以通过宿主机IP访问到8086。

那从外部来的流量为什么能够转发呢?

因为前面已经将所有的发往8086的流量转发到172.17.0.2上了。现在允许外部请求到宿主机上,就会触发上面的转发规则,就马上转发到172.17.0.2了。一气呵成。

需要注意的是,添加外部允许访问8086端口,必须在DOCKER链,添加INPUT链是没有用的。为什么呢?

iptables先判断nat表中的DOCKER链是否存在对应的端口的转发,如果有则使用filter表的DOCKER来过滤流量,而不再过滤INPUT链了。所以此时必须将允许外部IP访问的规则加在filter表的DOCKER才有用。

如果DOCKER链没有对应端口的转发,则转入INPUT链过滤。

至于为什么会这样,请阅读《一文讲清楚docker利用iptables实现容器网络的原理》。

这样操作之后,就为容器动态添加了端口映射了。把规则删除之后,端口映射即消失。

总结

容器的端口映射,核心就是一个端口转发。另外一个规则就是一个允许外部访问的规则。


原文地址: iptables实现docker容器动态端口映射实操-七秒鱼笔记

这篇关于iptables实现docker容器动态端口映射实操的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/932006

相关文章

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P