集装箱港口转发

Posted

技术标签:

【中文标题】集装箱港口转发【英文标题】:Container port forwarding 【发布时间】:2019-09-19 11:19:05 【问题描述】:

我有一个监听端口 3000 的二进制文件,但是,Google Cloud Run 希望我监听 $PORT 定义的端口,默认为 8080

有没有办法让我的容器绑定到 8080,然后将传入的请求转发到 3000?例如,通过向我的Dockerfile 添加一个简短的脚本和一行,它会使我的容器在 8080 上侦听并转发到我的二进制文件。

【问题讨论】:

您不能将您的应用程序修改为默认为 3000,但如果定义了 $PORT 则使用该端口代替吗? @codestation 问题指出这是一个二进制文件,大概是OP无法更改端口。 @dustin-ingram 是正确的。 PORT 环境变量在 Cloud Run 中由系统指定。解决方案确实需要确保容器接受服务指定的任何PORT 值的流量;只是目前这始终是8080,但这并不坚定。 【参考方案1】:

下面的代码未经测试,但大致思路是这样的:

    使用基于 shell 的启动脚本 启用 iptables 将流量从 srcPort 路由到 dstPort 执行原始二进制文件

在 Dockerfile 中,将 ENTRYPOINT 替换为启动脚本:

FROM debian:9 # or another container that has iptables available
RUN apt-get install iptables
EXPOSE 8080
ENTRYPOINT /bin/startup.sh /bin/original

然后编写一个启动脚本,启用iptables并将容器内8080上的入站流量转发到3000:

#!/usr/bin/env bash
set -e

sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf
sysctl -p
systemctl start iptables

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j REDIRECT --to-port 3000
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 8080 -j REDIRECT --to-port 3000


unshift 
exec "$@"

【讨论】:

不幸的是,脚本失败了。 (1) debian:9 不包括 sysctldebian:8 包括; (2)我认为(!?)如果既不以--privileged 运行容器也不使用--sysctl=net.ipv4.ip_forward=1 (他不能在Cloud Run 上),你不能在容器内修改net.ipv4.ip_forward; (3) 您想在安装前使用sudo apt-get update && sudo apt-get -y install iptables 刷新软件包。 @steren -- 希望您有 FR 允许在 Cloud Run 中进行端口转发|发布 ;-)【参考方案2】:

如果您可以安装运行第二个进程并在主进程中启动它,则使用以下命令安装并运行 socat:

socat tcp-listen:8080,fork,reuseaddr tcp-connect:localhost:3000

这样,socat 将绑定到 8080 端口并将所有流量发送到您的二进制文件正在侦听的端口 3000。

在 Cloud Run 之外:如果您无法触摸映像或容器,那么您仍然可以在其他容器上运行 socat,例如:

version: '3.5'
services:
  proxy:
    image: alpine/socat:1.0.3
    command: tcp-listen:8080,fork,reuseaddr tcp-connect:myservice:3000
    networks:
      - mynet
networks:
  mynet:
    external: true

mynet 是运行二进制文件的网络,myservice 是二进制文件的服务名称。

【讨论】:

您是否在 Google Cloud Run 上对此进行了测试和验证? @JohnHanley,不,但第一个选项应该可以正常工作(重定向流量的附加过程),否则 Cloud Run 中的某些内容已损坏(我过去曾成功使用 socat 与 docker 容器)。当然,如果其他一切都失败了,OP 可以对二进制文件进行十六进制编辑以更改端口号(假设二进制文件未签名/混淆)。 我认为 Cloud Run 无法实现您答案的第二部分。虽然 Cloud Run 运行的是容器,但它不是 Docker 容器平台。整个容器的监听端口(一个端口)由谷歌控制。无法通过名称等访问 Docker 网络。另一个容器的地址将是未知的。有多少个容器同时运行是未知的(此时)。 Cloud Run 被设计为一个 HTTP 请求/响应系统,可根据每秒请求进行扩展。 @john-hanley 是正确的,您不能(尽管这是一个很好的解决方案)在 Cloud Run 上运行类似“sidecar”的容器来代理流量(这是 Google 应该特别考虑的事情,因为这是( a) 将成为一个相当普遍的问题;(b) 底层模型是 Kubernetes Pod,这是 Kubernetes 的常见模式。 虽然在同一个容器中运行socat 可能会解决问题,但在容器中运行某种形式的代理可能是唯一的解决方案,但这与良好做法背道而驰在单个容器中运行多个进程。

以上是关于集装箱港口转发的主要内容,如果未能解决你的问题,请参考以下文章

模块化建筑参选企业巡展(三十四):集装箱主题餐厅

容器技术对港口航运物流业大数据发展的影响

基于PaddleOCR的集装箱箱号检测识别

基于PaddleOCR的集装箱箱号检测识别

天津港焦炭码头牵手图扑软件,可视化解锁智慧焦炭港口

新基建+新科技,智慧港口船舶抢抓数字化转型先机