问题描述
我目前正在公司使用Docker-Compose运行一个开发栈,向开发人员提供编写我们的应用程序所需的所有东西。它特别包括:
- 一个Gitlab容器()来管理私有GIT存储库,
- 一个Jenkins容器(),用于构建和持续集成,
- 一个Archiva容器()来管理Maven存储库。
为了通过HTTPS保护服务并将其暴露给外界,我安装了优秀的nginx-proxy容器(),允许自动化的nginx代理配置离子使用容器上的环境变量,以及自动化HTTP到HTTPS重定向。
DNS配置为将停靠服务的每个公共URL映射到主机的IP。 >
最后,使用Docker-Compose,我的docker-compose.yml文件如下所示:
c> archiva.my-domain.com 被解析为Docker容器中的公共主机IP,来自dockerized服务的请求不由nginx-proxy代理。
据我所知,docker-nginx正在处理来自主机网络的请求,但不关心来自内部容器网络(_dockerconfig_default_ for Docker-Compose堆栈)的那些。
你可以说,为什么我需要使用代理从容器?当然,我可以使用Jenkins容器的URL http:// archiva:8080 ,这样就可以了。但是这种配置是不可扩展的。
例如,使用Gradle构建来编译一个应用程序,build.gradle需要通过 https://archiva.my-domain.com 。如果构建是从开发人员工作站启动的,而不是通过jenkins容器启动,那么它将工作。
另一个例子是由OAuth GitLab服务在Jenkins中的身份验证,相同的URL GitLab身份验证需要从外部和Jenkins容器内部获得 。
我的问题是:如何配置nginx-proxy来代理从容器到另一个容器的请求?
我没有看到任何话题讨论这个问题,我不了解足够的问题来构建一个nginx配置的解决方案。
任何帮助将非常感谢。
解决方案BMitch,可能性很好,这确实是一个iptables规则问题,而不是nginx-proxy的配置错误。
表过滤器的链INPUT的默认策略为 DROP ,并且没有规定来自容器IP(127.20.XX)的 ACCEPT 请求。
所以为了纪录,如果其他人面临同样的问题,我会给出一些细节。
要从外部访问容器,Docker将规则放在PREROUTING和FORWARD规则上,以允许外部IP从主机IP到容器IP的DNATed。这些默认规则允许任何外部IP,这就是为什么限制对容器的访问需要一些高级iptables自定义。
查看此链接的示例:
但是,如果您的容器需要访问主机资源(在主机上运行的服务,或在我的情况下,nginx -proxy容器监听HTTP / HTTPS主机端口并代理容器),您需要注意INPUT链的iptables规则。
实际上,请求来自容器并寻址到主机的Docker守护程序将被路由到主机网络堆栈,但则需要传递INPUT链(如请求 src IP是主机)。所以如果你想保护主机资源并让容器访问它们,不要记得添加这样的东西:
iptables -A INPUT -s 127.20.XX / 24 -j ACCEPT
其中127.20.XX / 24是虚拟网络您的集装箱正在运行。
非常感谢您的帮助。
I am currently running a development stack using Docker-Compose in my company, to provide to developers everything they need to code our applications.
It includes in particular:
- a Gitlab container (sameersbn/gitlab) to manage private GIT repositories,
- a Jenkins container (library/jenkins) for building and continuous integration,
- an Archiva container (ninjaben/archiva-docker) to manage Maven repositories.
In order to secure the services through HTTPS, and exposing them to the outside world, I installed the excellent nginx-proxy container (jwilder/nginx-proxy) which allows automated nginx proxy configuration using environment variables on containers, and automated HTTP to HTTPS redirection.
DNS are configured to map each public URL of dockerized services to the IP of the host.
Finally, using Docker-Compose, my docker-compose.yml file looks like this :
version: '2' services: nginx-proxy: image: jwilder/nginx-proxy ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - /var/config/nginx-proxy/certs:/etc/nginx/certs:ro postgresql: # Configuration of postgresql container ... gitlab: image: sameersbn/gitlab ports: - "10022:22" volumes: - /var/data/gitlab:/home/git/data environment: # Bunch of environment variables ... - VIRTUAL_HOST=gitlab.my-domain.com - VIRTUAL_PORT=80 - CERT_NAME=star.my-domain.com archiva: image: ninjaben/archiva-docker volumes: - /var/data/archiva:/var/archiva environment: - VIRTUAL_HOST=archiva.my-domain.com - VIRTUAL_PORT=8080 - CERT_NAME=star.my-domain.com jenkins: image: jenkins volumes: - /var/data/jenkins:/var/jenkins_home environment: - VIRTUAL_HOST=jenkins.my-domain.com - VIRTUAL_PORT=8080 - CERT_NAME=star.my-domain.com
For a developer workstation, everything works as expected. One can access the difference services through https://gitlab.my-domain.com, https://repo.my-domain.com and https://jenkins.my-domain.com.
The problem occurs when one of the dockerized service access another dockerized service. For instance, If I try to access https://archiva.my-domain.com from jenkins docker, I will get a timeout error from the proxy.
It seems that even if archiva.my-domain.com is resolved as the public host IP from the docker container, requests coming from dockerized services are not proxied by nginx-proxy.
As far as I understood, docker-nginx is handling requests coming from the host network, but does not care about the ones coming from the internal container network (_dockerconfig_default_ for a Docker-Compose stack).
You could say, why would I need to use the proxy from a container ? Of course, I could use URL http://archiva:8080 from Jenkins container, and it would work. But this kind of configuration is not scalable.
For example, using a Gradle build to compile one application, the build.gradle needs to declare my private repository through https://archiva.my-domain.com. It will work if build is launched from a developer workstation, but not through the jenkins container ...
Another example is an authentication in Jenkins by OAuth GitLab service, where the same URL GitLab authentication needs to be both available from the outside, and inside the Jenkins container.
My question here is then : How to configure nginx-proxy to proxy a request from a container to another container ?
I did not see any topic discussing this problem, and I do not understand enough the problem to build a solution on nginx configuration.
Any help would be really appreciated.
BMitch, the odds were good, it was indeed a iptables rules problem, and not a misconfiguration of nginx-proxy.
The default policy of chain INPUT for the table filter was DROP, and no rules was made to ACCEPT requests from the container IPs (127.20.X.X).
So for the record, I give some details of the situation if other people face the same problem.
To access containers from the outside world, Docker put rules on PREROUTING and FORWARD rules to allow external IPs to be DNATed from the host IP to the container IPs. Theses default rules allow any external IPs, and that is why limiting access to containers requires some advanced iptables customizations.
See this link for an example : http://rudijs.github.io/2015-07/docker-restricting-container-access-with-iptables/
But if your containers need to access host resources (services runing on the host, or in my case, a nginx-proxy container listening to HTTP/HTTPS host port and proxying to containers), you need to take care about the iptables rules of the INPUT chain.
In fact, a request coming from the container and addressed to the host will be routed to the host network stack by the Docker daemon, but will then need to pass the INPUT chain (as the request src IP is the host one). So if you want to protect host resources and let containers access them, do not remember to add something like this :
iptables -A INPUT -s 127.20.X.X/24 -j ACCEPT
Where 127.20.X.X/24 is the virtual network on which your containers are running.
Thank you a lot for your help.
这篇关于Docker nginx-proxy:容器之间的代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!