正在运行的Docker容器增加端口映射
为什么有这个需求
假设有如下情况:
- 这个服务很重要,很多服务在连,停服不知道会有什么影响。
- 服务是运行在 docker 里的,但是 docker 启动命令找不到了。
- 想给 docker 容器临时增加一个端口映射。
方法一、使用工具反向代理
这个方法性能不如上面的 iptables
规则,比如可以用 nginx
的 stream
四层代理,或者用 socat
一条命令搞定。
查看容器的 IP 地址
1 | docker inspect postgres |
在结果中找到 NetworkSettings
-> Networks
-> <你的网络名称>
-> IPAddress
1 | # 安装 socat |
方法二、参照 Docker 原生的方式
docker 的 -p 命令来进行端口映射,本质上也是维护了一套 iptables 规则来实现的,docker-proxy 会维护 docker 需要的 iptables 规则,执行 iptables-save
可以查看所有的规则 (iptables-save
并不会真的 save,想保存 iptables
规则还需要额外的操作)。
获取容器的 IP 地址
1 | docker inspect postgres |
在结果中找到 NetworkSettings
-> Networks
-> <你的网络名称>
-> IPAddress
查看 docker 的虚拟网卡
docker 的一个 bridge 网卡就对应了 linux 机器上的一个网卡,要新增端口映射,需要知道你的容器连接的虚拟网卡是什么。
比如我想让 Postgres 的 5432 端口映射到外网,先查看 Postgres 的容器信息。
1 | docker inspect postgres |
在结果中找到 NetworkSettings
-> Networks
-> <你的网络名称>
-> Gateway
,记录一下网关的 IP
1 | ip addr |
可以知道网卡的名称是 br-342eceae259f
配置 iptables 规则
比如我的容器 IP:172.18.0.2
Docker 虚拟网卡:br-342eceae259f
要映射的端口:5432
1 | iptables -A DOCKER-USER -o br-342eceae259f ! -i br-342eceae259f -d 172.18.0.2/32 -m tcp -p tcp --dport 5432 -j ACCEPT |
不需要做 SNAT,因为 Docker 默认已经做了 SNAT 了。
方法三、传统的 iptables 规则
1 |
|
如果规则不加,或加在了 DOCKER-USER 的下面,会兜兜转转,最后匹配到了 DROP
知道了原理后,那么还有一种方法:删除这个 DROP(不要这么做)
1 | # iptables -D DOCKER ! -i docker0 -o docker0 -j DROP |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 杂烩饭!
评论