简体   繁体   English

Docker nginx-proxy:容器之间的代理

[英]Docker nginx-proxy : proxy between containers

I am currently running a development stack using Docker-Compose in my company, to provide to developers everything they need to code our applications. 我目前正在我公司使用Docker-Compose运行开发堆栈,为开发人员提供编写应用程序所需的一切。

It includes in particular: 它特别包括:

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. 为了通过HTTPS保护服务并将它们暴露给外界,我安装了优秀的nginx-proxy容器( jwilder / nginx-proxy ),它允许在容器上使用环境变量进行自动nginx代理配置,以及自动HTTP到HTTPS重定向。

DNS are configured to map each public URL of dockerized services to the IP of the host. DNS配置为将dockerized服务的每个公共URL映射到主机的IP。

Finally, using Docker-Compose, my docker-compose.yml file looks like this : 最后,使用Docker-Compose,我的docker-compose.yml文件如下所示:

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 . 可以通过https://gitlab.my-domain.com : https://repo.my-domain.comhttps://jenkins.my-domain.com访问差异服务。

The problem occurs when one of the dockerized service access another dockerized service. 当其中一个dockerized服务访问另一个dockerized服务时,会发生此问题。 For instance, If I try to access https://archiva.my-domain.com from jenkins docker, I will get a timeout error from the proxy. 例如,如果我尝试从jenkins docker访问https://archiva.my-domain.com ,我将从代理获得超时错误。

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. 似乎即使archiva.my-domain.com被解析为来自docker容器的公共主机IP, 来自dockerized services的请求也不会被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). 据我所知,docker-nginx正在处理来自主机网络的请求,但不关心来自内部容器网络的请求(对于Docker-Compose堆栈,_dockerconfig_default_)。

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. 当然,我可以使用来自Jenkins容器的URL http://archiva:8080 ,它可以工作。 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 . 例如,使用Gradle构建来编译一个应用程序,build.gradle需要通过https://archiva.my-domain.com声明我的私有存储库。 It will work if build is launched from a developer workstation, but not through the jenkins container ... 如果从开发人员工作站启动构建,但不通过jenkins容器启动,它将起作用...

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. 另一个例子是通过OAuth的GitLab服务,其中相同的URL GitLab认证必须可以从外部,并且詹金斯容器内部在詹金斯的认证。

My question here is then : How to configure nginx-proxy to proxy a request from a container to another container ? 我的问题是: 如何配置nginx-proxy来代理从容器到另一个容器的请求?

I did not see any topic discussing this problem, and I do not understand enough the problem to build a solution on nginx configuration. 我没有看到任何讨论这个问题的话题,我对nginx配置构建解决方案的问题不够了解。

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. BMitch,赔率很高,这确实是一个iptables规则问题,而不是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.XX). filter的链INPUT的默认策略是DROP ,并且没有规则来自容器IP(127.20.XX)的ACCEPT请求。

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. 为了从外部访问容器,Docker对PREROUTING和FORWARD规则规定了允许外部IP从主机IP到容器IP的DNAT。 Theses default rules allow any external IPs, and that is why limiting access to containers requires some advanced iptables customizations. 这些默认规则允许任何外部IP,这就是为什么限制对容器的访问需要一些高级iptables自定义。

See this link for an example : http://rudijs.github.io/2015-07/docker-restricting-container-access-with-iptables/ 请参阅此链接以获取示例: 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. 但是如果你的容器需要访问主机资源(在主机上运行的服务,或者在我的情况下,一个nginx-proxy容器监听HTTP / HTTPS主机端口并代理到容器),你需要注意iptables的规则。 INPUT链。

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). 实际上,来自容器并发送到主机的请求将由Docker守护程序路由到主机网络堆栈, 但是然后需要传递INPUT链(因为请求src IP是主机端)。 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.XX/24 is the virtual network on which your containers are running. 127.20.XX / 24是运行容器的虚拟网络。

Thank you a lot for your help. 非常感谢你的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM