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容器动态端口映射实操-七秒鱼笔记

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/2346.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(2024)Visual Studio的介绍、安装与使用

Visual Studio介绍 1.Visual Studio是什么? Visual Studio是微软公司推出的一款开发工具包系列产品,它是一个基本完整的开发工具集,为软件开发者提供了整个软件生命周期中所需的大部分工具。 2.Visual Studio的定义 Visual Studio是美国微软公…

网盘_游戏_博客自动化部署(Nginx多项目部署)

目录 一.前提介绍 二.环境介绍 三.自述(脚本) 四.关于Nginx多项目部署 一.前提介绍 在我之前的博客里详细介绍了上述项目的部署,那么如何使用简单脚本自动部署和使用Nginx多项目部署是本文来介绍的基础篇章。 二.环境介绍 CentOS Linux…

fawawf

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话: 知不足而奋进,望远山而前行&am…

【Linux】文件目录及路径表示

1. Linux目录结构 在 Linux 系统中,有几个目录是比较重要的,平时需要注意不要误删除或者随意更改内部文件。 /etc: 这个是系统中的配置文件,如果更改了该目录下的某个文件可能会导致系统不能启动。 /bin, /sbin, /usr/bin, /usr…

java泛型介绍

Java 泛型是 JDK 5 引入的一个特性,它允许我们在定义类、接口和方法时使用类型参数,从而使代码更加灵活和类型安全。泛型的主要目的是在编译期提供类型参数,让程序员能够在编译期间就捕获类型错误,而不是在运行时才发现。这样做提…

小程序AI智能名片S2B2C商城系统:解锁内容深耕新境界,助力品牌企业高效定制内容策略

在数字化时代,内容营销已成为品牌企业获取市场份额、增强用户黏性的关键武器。然而,面对海量的互联网信息和复杂多样的社交媒体平台,如何有效地深耕内容,成为众多品牌企业面临的难题。 传统的内容分类与识别方式,往往依…

【数据分析面试】28. 20个Python问答题 (入门级考察:基础操作、数据处理与分析统计)

今天的20个问题考察了 Python 的基础能力,包括数据结构、基本操作、数据处理、数据分析和统计等方面。无论是从事数据分析、机器学习还是其他数据相关工作,这些都是必不可少的基础技能。 数据结构与基础操作: 什么是 Pandas 库?它…

中兴5G随身wifi怎么样?中兴5G随身wifiVS格行5G随身wifi对比测评!公认最好的随身WiFi的格行随身WiFi真实测评!随身WiFi哪个品牌好?

随着各大品牌5G随身wifi的横空出世,其中中兴和格行5G随身wifi的呼声越来越高,那么性能上谁更胜一筹?套餐费用谁更亲民?售后保障谁更到位?今天就来一个全方位测评对比! 一,首先是设备的整体外观&…

uniapp:小白1分钟学会使用webSocket(可无脑复制)

uni.connectSocket() uni.$emit页面通信 项目中使用uni.connectSocket()创建webSocket的总结,代码可无脑复制,直接使用。 1、main.js 引入vuex import store from ./store; Vue.prototype.$store store;vuex中封装webSocket 2、vuex的:index…

linux autogroup

一:概述 对于linux autogroup的作用,很多同学可能是听说过,但,并未验证过。 考虑下面场景,开两个terminal,T1和T2,在T1中运行进程P1,P1开启9个线程编译代码,在T2中运行…

yield函数怎么理解?

目录 白话系列: 例子🌰: 什么叫暂停 yield和next搭配使用 例子🌰: 白话系列: 可以暂停,可以生成,next一个,yield一个 例子🌰: def generat…

CUDA线程管理

核函数在主机端启动时,执行会转移到设备上,并且将控制权转移回主机。当核函数在GPU上运行时,主机可以运行其他函数。因此,主机与核函数是异步的。 此时,设备端也就是GPU上会产生大量的线程,并且每个线程都…

(七)小案例银行家应用程序-申请贷款-some方法和every方法

some方法 ● 我们先回顾一下includes方法 console.log(movements.includes(-130));只要数组中存在-130这个值,就会返回true,否则就会返回flase ● 而some方法只要达成某一个条件就会返回true,否则就返回flase const someMethod movement…

stm32开发之threadx之modulex模块文件的生成脚本项目

前言 为了保证在window上运行,且体积小的问题,所以采用c语言编写生成脚本,将相关路径由json文件进行配置,使用了一个cjson库进行解析项目构建使用的是cmake 项目代码 CMakeLists文件 cmake_minimum_required(VERSION 3.27) project(txm_bat_script C…

Day13-Java进阶-IO字节流及其练习题

1. IO流介绍 2. IO 流体系结构 字节流读取纯文本文件会出现乱码问题 2.1 FileOutputStream 字节输出流 package com.itheima.stream.output;import java.io.FileOutputStream; import java.io.IOException;public class FileOutputStreamDemo3 {/*IO流的异常处理方式: jdk7版本…

socket编程——tcp

在我这篇博客:网络——socket编程中介绍了关于socket编程的一些必要的知识,以及介绍了使用套接字在udp协议下如何通信,这篇博客中,我将会介绍如何使用套接字以及tcp协议进行网络通信。 1. 前置准备 在进行编写代码之前&#xff…

C语言学习/复习30--结构体的声明/初始化/typedef改名/内存对齐大小计算

一、自定义数据类型 二、结构体 1.结构体的定义(与数组相对比) 2.结构体全局/局部变量的定义 3.typedef对结构体改名 4.匿名结构体类型的声明 注意事项1: 匿名后必须立即创建结构体变量 、 5.结构体与链表节点定义 注意事项1&…

Datawhale ChatGPT基础科普

根据课程GitHub - datawhalechina/hugging-llm: HuggingLLM, Hugging Future. 摘写自己不懂得一些地方,具体可以再到以上项目地址 LM:这是ChatGPT的基石的基石。 Transformer:这是ChatGPT的基石,准确来说它的一部分是基石。 G…

nodejs工具模块学习

util 是一个Node.js 核心模块,提供常用函数的集合; util.inspect(object,[showHidden],[depth],[colors]) 是一个将任意对象转换 为字符串的方法,通常用于调试和错误输出; 如果只有一个参数 object,是要转换的对象&…

英伟达AI系列免费公开课

英伟达公开课官网地址 Augment your LLM Using Retrieval Augmented Generation Building RAG Agents with LLMs langchain的workflow: ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c90cb157c9c84bb5b3da380ec56f5c2a.png Generative AI Explained