使用docker容器作为代理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用docker容器作为代理相关的知识,希望对你有一定的参考价值。

一般来说,我试图使用docker容器作为同一网络覆盖内的其他docker容器的HTTP代理。我们称之为代理容器网关。假设网关配置了所有必需的CA证书,此网关假设将其收到的HTTP请求更改为HTTPS请求,并将其转发到外部世界。

现在让我们详细说明,我正在使用docker swarm和services + replicas,网关在端口80上提供一些api,容器使用Gateway的服务名称+端口80来请求这个api(与代理无关)需要),例如:

http://gateway:80/api/logout

我也希望将此端口用于代理,这意味着其他容器可以将HTTP请求发送到端口80上的某些IP(而不是DNS),并且此请求将通过网关,而网关将查看http请求并看到此消息不是“他”,它将执行httpS(在端口443上)请求到实际的外部服务器。

我无法在下面的链接中使用Docker的代理解决方案:

https://docs.docker.com/engine/admin/systemd/#httphttps-proxy

因为HTTP代理的这种解决方案仅适用于已经运行的代理,而不是dockerized代理。 (如果我使用它,docker将无法从repo获取图像,因为它将查找不存在的代理,因为docker本身尚未启动Gateway容器)。

所以,这让我想到了这个问题。如何在不使用网关服务名称的情况下将内部容器请求转发到网关。

我认为iptables是唯一的选择,但是如何?我无法使用网关IP,因为网关是3个虚拟机上的副本,并且IP发生了变化,无论如何,任何发送http://some_external_server_ip:80/some_api的容器都需要以某种方式通过网关。

TLDR

我可以在iptables(使用docker链和PREROUTING链)中执行某些操作,将端口80上的所有数据包(由其覆盖网络中的容器发送)转发到名为Gateway的服务容器中,同时忽略目标IP吗? (仅通过端口识别数据包并将其转发给特定的contianer)

希望这很清楚... =)

答案

所以,我通过一些tcpdump调查找到了答案。

在此链接中使用docker的HTTP_PROXY配置时:https://docs.docker.com/engine/admin/systemd/#httphttps-proxy它不能处理同一网络内的容器,因为上面的链接描述了外部通信的代理(代理到覆盖网络之外)。

因此,假设Container A是代理容器,而容器B是一些其他容器,它向某些外部ip运行HTTP请求,并假设这两个容器都位于同一个docker的覆盖网络(docker的某个内部网络)上。为了从容器B出来的HTTP请求将通过容器A,我们需要在容器B中定义环境变量:

  1. http_proxy - 此环境变量将保存代理容器的名称和端口,例如:http_proxy = containerA:8080注意:(containerA是容器A的服务名称)
  2. no_proxy - 此环境变量将保存所有不应通过代理的ips。例如,您不希望容器B的内部网络通信将通过容器A,例如,如果容器B想要在HTTP上与容器C通信,假设它们都在同一个覆盖网络上,那么,您希望它们没有容器A自由地“说话”充当代理人。在这种情况下,你将把覆盖网络的子网(所有容器都位于其中)放在no_proxy环境变量(以及localhost访问)中,在我的例子中它是这样的:no_proxy = 10.0.0.0 / 24 ,本地主机,127.0.0.1。

当在容器B上设置这两个环境变量时,容器B的所有外部HTTP通信都将通过容器A.

注意:“外部通信”表示使用一些未知用于泊坞窗服务名称的外部IP。

以上是关于使用docker容器作为代理的主要内容,如果未能解决你的问题,请参考以下文章

带有容器的 Jenkins Docker Sidecar 运行守护程序命令

在 Jenkins Docker 代理中使用测试容器:容器无法启动,NoRouteToHostException

nginx 反向代理可以访问多个 docker 容器

对 docker 容器使用 nginx 反向代理

docker 安装 nginx 并配置反向代理

在 AWS ECS 中将带有卷参数的 docker 容器作为任务定义或服务运行