本文介绍了Docker nginx-proxy : 容器之间的代理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前在我的公司使用 Docker-Compose 运行一个开发堆栈,为开发人员提供他们编写我们的应用程序所需的一切.

I am currently running a development stack using Docker-Compose in my company, to provide to developers everything they need to code our applications.

它特别包括:

  • 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.

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

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 配置为将 dockerized 服务的每个公共 URL 映射到主机的 IP.

DNS are configured to map each public URL of dockerized services to the IP of the host.

最后,使用 Docker-Compose,我的 docker-compose.yml 文件如下所示:

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

对于开发人员工作站,一切都按预期进行.可以通过https://gitlab.my-domain.comhttps://repo.my-domain.comhttps访问不同的服务://jenkins.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.

当一个dockerized服务访问另一个dockerized服务时出现问题.例如,如果我尝试从 jenkins docker 访问 https://archiva.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.

似乎即使 archiva.my-domain.com 被解析为来自 docker 容器的公共主机 IP,来自 dockerized 服务的请求也不会被 nginx-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.

据我所知,docker-nginx 正在处理来自主机网络的请求,但不关心来自内部容器网络的请求(Docker-Compose 堆栈的 _dockerconfig_default_).

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).

您可能会说,为什么我需要使用容器中的代理?当然,我可以使用来自 Jenkins 容器的 URL http://archiva:8080,它会起作用.但是这种配置是不可扩展的.

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.

例如,使用 Gradle build 编译一个应用程序,build.gradle 需要通过 https://archiva.my-domain.com 声明我的私有存储库.如果构建是从开发人员工作站启动的,而不是通过 jenkins 容器启动,它将起作用......

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 ...

另一个例子是 OAuth GitLab 服务在 Jenkins 中的身份验证,其中相同的 URL GitLab 身份验证需要两者可从外部和 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.

我的问题是:如何配置 nginx-proxy 将请求从一个容器代理到另一个容器?

My question here is then : How to configure nginx-proxy to proxy a request from a container to another container ?

我没有看到任何讨论这个问题的话题,我对这个问题的理解不够,无法在 nginx 配置上构建解决方案.

I did not see any topic discussing this problem, and I do not understand enough the problem to build a solution on nginx configuration.

任何帮助将不胜感激.

推荐答案

BMitch,胜算不错,确实是 iptables 规则问题,而不是 nginx-proxy 配置错误.

BMitch, the odds were good, it was indeed a iptables rules problem, and not a misconfiguration of nginx-proxy.

filter链INPUT的默认策略是DROP,并且没有对来自容器IP的ACCEPT请求制定规则(127.20.XX).

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.

为了从外部访问容器,Docker 将规则放在 PREROUTING 和 FORWARD 规则上,以允许外部 IP 从主机 IP 到容器 IP 进行 DNATed.这些默认规则允许任何外部 IP,这就是限制对容器的访问需要一些高级 iptables 自定义的原因.

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.

查看此链接以获取示例:http://rudijs.github.io/2015-07/docker-restricting-container-access-with-iptables/

See this link for an example : http://rudijs.github.io/2015-07/docker-restricting-container-access-with-iptables/

但是如果你的容器需要访问主机资源(在主机上运行的服务,或者在我的例子中是一个监听 HTTP/HTTPS 主机端口并代理到容器的 nginx-proxy 容器),你需要注意 iptablesINPUT 链的规则.

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.

事实上,来自容器并发送到主机的请求将被 Docker 守护进程路由到主机网络堆栈,但是然后需要传递 INPUT 链(作为请求src IP 是主机的 IP).所以如果你想保护主机资源,让容器访问它们,不要记得添加这样的东西:

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

其中 127.20.X.X/24 是运行容器的虚拟网络.

Where 127.20.X.X/24 is the virtual network on which your containers are running.

非常感谢您的帮助.

这篇关于Docker nginx-proxy : 容器之间的代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-07 00:09