【问题标题】:Docker nginx-proxy : proxy between containersDocker nginx-proxy:容器之间的代理
【发布时间】:2017-02-21 23:44:51
【问题描述】:

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

具体包括:

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

DNS 配置为将 dockerized 服务的每个公共 URL 映射到主机的 IP。

最后,使用 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

对于开发人员工作站,一切都按预期工作。可以通过https://gitlab.my-domain.comhttps://repo.my-domain.comhttps://jenkins.my-domain.com访问差异化服务。

当一个 dockerized 服务访问另一个 dockerized 服务时会出现问题。例如,如果我尝试从 jenkins docker 访问 https://archiva.my-domain.com,我会从代理收到超时错误。

似乎即使archiva.my-domain.com 被解析为来自 docker 容器的公共主机 IP,来自 dockerized 服务的请求也不会被 nginx-proxy 代理。

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

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

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

另一个示例是通过 OAuth GitLab 服务在 Jenkins 中进行身份验证,其中相同的 URL GitLab 身份验证需要在外部和 Jenkins 容器内部都可用。

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

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

任何帮助将不胜感激。

【问题讨论】:

  • 我删除了我的答案,因为它与问题无关。我在这里留下了nginx-proxy 的作者关于 docker compose 的信息。 目前这不适用于 docker-compose 的新 v2 语法(由于与新的网络覆盖不兼容,请参阅 #304)。它在使用旧的 docker-composer 语法时确实有效。
  • 检查 docker 主机上的 iptables 和路由设置。还要检查 docker 代理(主机上的端口绑定服务)和 nginx-proxy 正在侦听哪些接口。由于防火墙规则,容器不允许连接到主机上的端口的可能性很大。确保你也在检查 nat 和 mangle iptables。
  • 你需要链接到需要内部通信的容器,imo。

标签: nginx docker proxy docker-compose jwilder-nginx-proxy


【解决方案1】:

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

filter 表的链 INPUT 的默认策略是DROP,并且没有对来自容器 IP (127.20.X.X) 的 ACCEPT 请求进行任何规则。

因此,作为记录,如果其他人面临同样的问题,我会详细说明情况。

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

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

但是如果您的容器需要访问主机资源(在主机上运行的服务,或者在我的情况下,一个 nginx-proxy 容器监听 HTTP/HTTPS 主机端口并代理到容器),您需要注意 iptables INPUT 链的规则。

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

iptables -A INPUT -s 127.20.X.X/24 -j ACCEPT

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

非常感谢您的帮助。

【讨论】:

  • 要进一步详细说明这个答案,请使用docker network inspect my_network_name 并查找“IPAM.Config.Subnet”。这就是您需要接受的虚拟网络。
猜你喜欢
  • 2016-07-04
  • 2017-10-12
  • 2017-01-22
  • 2021-05-04
  • 1970-01-01
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 2019-03-11
相关资源
最近更新 更多