我有一对在主机上运行的docker容器,这些容器一起使我的应用程序完成。 因此,对于我的应用程序的每个迭代/实例,都需要一对Docker容器才能运行。 到目前为止,我正在使用–link参数,同时运行第二个容器来链接第一个容器,并从主机文件获取第一个容器的IP以编程方式使用它。
现在,我需要为第二个Docker容器设置透明代理。 因此第二个容器的所有http(端口80)stream量都应该经过第一个容器的端口8080。
第一个容器IP: 172.17.0.4 (代理服务在端口8080上运行)。 第二个容器IP: 172.17.0.6 (有浏览器之类的客户端工具)。 我想将172.17.0.6的所有httpstream量(端口80 )转发到172.17.0.4的8080端口。
即)到172.17.0.4 <—> 8080的172.17.0.6的80
我已经尝试添加上述configuration的第二个容器内的iptables规则。 但他们都没有工作。
~# sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 172.17.0.4:8080
不起作用。
~# sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 172.17.0.4:8080
不起作用。
~# sudo iptables -t nat -A POSTROUTING -j MASQUERADE
所以我的问题是,我怎样才能configuration一个透明代理docker容器,可以转发指定端口的所有通信到另一个容器的端口?
PS: 如果我手动将代理设置添加到第二个容器中的浏览器。 它工作正常。 但我想为整个容器设置透明代理,而不仅仅是浏览器。 这样来自第二个容器内的任何工具的任何networking请求都将被转发到第一个容器的代理端口。
我已经阅读了一些反向代理使用nginx / HAProxy一起运行的所有容器的教程。 但我想configuration单个容器与它自己的代理容器作为一对。
谢谢大家的时间来回答。 基本上我试图做的是代理第二个容器的传出/始发stream量( 注意:我不是试图代理传入的stream量,所以不能使用Apache mod_proxy或Nginx的proxy_pass。这些模块适用于传入stream量)。 第一个容器在端口8080上运行代理服务。
正如Thierno所build议的,我可以使用http_proxy和https_proxy ENVvariables来代理外出stream量,但不幸的是, 不是所有在您的操作系统中运行的应用程序/服务都会遵守这些http_proxy和https_proxy ENVvariables。 有强制跳过代理设置的应用程序。 这就是为什么我想使用iptables来执行stream量规则的原因 。 因此没有任何应用程序/服务可以跳过代理。
我在前面的设置中所做的错误是,我试图将传入的stream量路由到代理服务器的端口80到8080。 由于第一个容器没有任何传入的stream量,它将无法正常工作,并且PREROUTE / POSTROUTEstream量在逻辑上是错误的,以实现我所寻找的。 要发送/发送stream量,我们需要使用iptables的OUTPUT链 。
我已经使用iptables组合的RedSocks强制从服务器的完整传出stream量的代理。 这里是我使用的iptablesconfiguration:
#为RedSocks创build新链
root# iptables -t nat -N REDSOCKS
#忽略局域网和其他一些保留地址
root# iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN root# iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN root# iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN root# iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN root# iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN root# iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN root# iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN root# iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
#将所有httpredirect到redsocks本地端口
root# sudo iptables -t nat -A REDSOCKS -p tcp --dport 80 -j REDIRECT --to-ports 12345
httpsstream量#只需要replace端口80 443
#在eth0的所有出站stream量上使用所有REDSOCKS链
root# sudo iptables -t nat -A OUTPUT -p tcp -o eth0 -j REDSOCKS
现在,configurationredsocks来侦听inputstream量的本地端口12345,并将其转发到代理服务器的IP和端口。 要做到这一点像这样编辑redsocks.conf ,
redsocks { local_ip = 127.0.0.1; local_port = 12345; ip = 172.17.0.4; port = 8080; type = http-relay; }
只需保存conf并重新启动redsocks服务 。 现在所有从第一个容器发出的stream量将被强制使用代理。 ( 注意:我已经使用iptables-persistent在服务器重启时保留规则)实际上,我通过在iptablesconfiguration中添加另一行来实现http和https通信。 虽然它不是一个透明的代理,但它为我做的工作。
互信链接不是docker工人所拥有的,据我所知(运行时显示的信息是关于一个集装箱的后台移植或者回馈给祖先的)。 这可能就是为什么大多数教程都有第三个共同的祖先,即“代理”被使用。
如果你愿意使用无花果或编织这样的框架,我相信这些框架有yaml或者jsonconfiguration文件,那么你可能只需要两个相反的容器来设置它。
如果你愿意有第三个,那么所有的港口和pipe道可以通过共同的祖先为你的兄弟容器。
我认为使用$http_proxy env var应该有所帮助。
您可以在docker文件(容器#2)中设置一个入口点,以在容器启动时导出env var。 在你的入口处,你应该有这样的东西:
export http_proxy=http://$CONATAINER1_PORT_8080_TCP_ADDR:$CONATAINER1_PORT_8080_TCP_PORT
我不知道你的客户端(浏览器)是否可以使用$ http_proxy env var,但它应该存在一个类似的方法。 例如,对于Firefox:
user_pref("network.proxy.http", "$CONATAINER1_PORT_8080_TCP_ADDR"); user_pref("network.proxy.http_port", $CONATAINER1_PORT_8080_TCP_PORT); user_pref("network.proxy.type", 1);
小贴士:在第二个容器上使用printenv来知道你应该在入口点使用什么variables名称