Docker nginx-proxy : 容器之间的代理
Docker nginx-proxy : proxy between containers
我目前 运行 在我的公司使用 Docker-Compose 的开发堆栈,为开发人员提供他们编写我们的应用程序所需的一切。
具体包括:
- 用于管理私有 GIT 存储库的 Gitlab 容器 (sameersbn/gitlab),
- 一个用于构建和持续集成的 Jenkins 容器 (library/jenkins),
- 用于管理 Maven 存储库的 Archiva 容器 (ninjaben/archiva-docker)。
为了通过 HTTPS 保护服务并将它们暴露给外界,我安装了优秀的 nginx-proxy 容器 (jwilder/nginx-proxy),它允许使用容器上的环境变量自动配置 nginx 代理,并且自动 HTTP 到 HTTPS 重定向。
DNS 配置为将每个 public URL 的 docker 化服务映射到主机的 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.com
、https://repo.my-domain.com
和 https://jenkins.my-domain.com
.
访问不同的服务
当其中一个 docker 化服务访问另一个 docker 化服务时会出现问题。例如,如果我尝试从 jenkins docker 访问 https://archiva.my-domain.com
,我将收到来自代理的超时错误。
似乎即使 archiva.my-domain.com
被解析为来自 docker 容器的 public 主机 IP,来自 docker 化服务的 请求没有被 nginx-proxy 代理。
据我了解,docker-nginx 正在处理来自主机网络的请求,但不关心来自内部容器网络的请求(_dockerconfig_default_ 对于 Docker-组成堆栈)。
您可能会说,为什么我需要使用容器中的代理?当然,我可以使用 Jenkins 容器中的 URL http://archiva:8080
,它会起作用。但是这种配置是不可扩展的。
例如,使用Gradle构建编译一个应用程序,build.gradle需要通过https://archiva.my-domain.com
声明我的私有仓库。如果构建是从开发人员工作站启动的,但不是通过 jenkins 容器启动的,它将工作...
另一个例子是通过 OAuth GitLab 服务在 Jenkins 中进行身份验证,其中相同的 URL GitLab 身份验证需要 both 从外部和 Jenkins 内部可用容器。
那么我的问题是:如何配置 nginx-proxy 以将请求从一个容器代理到另一个容器?
我没有看到任何讨论这个问题的话题,我对这个问题的理解不够,无法在 nginx 配置上构建解决方案。
任何帮助将不胜感激。
BMitch,可能性很大,确实是iptables规则问题,而不是nginx-proxy配置错误。
table filter
的链 INPUT 的默认策略是 DROP
,并且没有对来自容器 IP (127.20.X.X).
所以为了记录,如果其他人遇到同样的问题,我会提供一些情况的细节。
为了从外部世界访问容器,Docker 在 PREROUTING 和 FORWARD 规则上设置规则以允许外部 IP 从主机 IP DNAT 到容器 IP。这些默认规则允许任何外部 IP,这就是为什么限制对容器的访问需要一些高级 iptables 自定义。
请参阅此 link 示例:http://rudijs.github.io/2015-07/docker-restricting-container-access-with-iptables/
但是如果你的容器需要访问主机资源(在主机上运行的服务,或者在我的例子中,一个 nginx-proxy 容器监听 HTTP/HTTPS 主机端口并代理到容器),你需要采取关心 INPUT 链的 iptables 规则。
实际上,来自容器并发往主机的请求将由 Docker 守护程序路由到主机网络堆栈,但是 将需要传递 INPUT 链(因为请求 src
IP 是主机一个)。所以如果你想保护主机资源,让容器访问它们,不要记得添加这样的东西:
iptables -A INPUT -s 127.20.X.X/24 -j ACCEPT
其中 127.20.X.X/24 是您的容器所在的虚拟网络 运行.
非常感谢您的帮助。
我目前 运行 在我的公司使用 Docker-Compose 的开发堆栈,为开发人员提供他们编写我们的应用程序所需的一切。
具体包括:
- 用于管理私有 GIT 存储库的 Gitlab 容器 (sameersbn/gitlab),
- 一个用于构建和持续集成的 Jenkins 容器 (library/jenkins),
- 用于管理 Maven 存储库的 Archiva 容器 (ninjaben/archiva-docker)。
为了通过 HTTPS 保护服务并将它们暴露给外界,我安装了优秀的 nginx-proxy 容器 (jwilder/nginx-proxy),它允许使用容器上的环境变量自动配置 nginx 代理,并且自动 HTTP 到 HTTPS 重定向。
DNS 配置为将每个 public URL 的 docker 化服务映射到主机的 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.com
、https://repo.my-domain.com
和 https://jenkins.my-domain.com
.
当其中一个 docker 化服务访问另一个 docker 化服务时会出现问题。例如,如果我尝试从 jenkins docker 访问 https://archiva.my-domain.com
,我将收到来自代理的超时错误。
似乎即使 archiva.my-domain.com
被解析为来自 docker 容器的 public 主机 IP,来自 docker 化服务的 请求没有被 nginx-proxy 代理。
据我了解,docker-nginx 正在处理来自主机网络的请求,但不关心来自内部容器网络的请求(_dockerconfig_default_ 对于 Docker-组成堆栈)。
您可能会说,为什么我需要使用容器中的代理?当然,我可以使用 Jenkins 容器中的 URL http://archiva:8080
,它会起作用。但是这种配置是不可扩展的。
例如,使用Gradle构建编译一个应用程序,build.gradle需要通过https://archiva.my-domain.com
声明我的私有仓库。如果构建是从开发人员工作站启动的,但不是通过 jenkins 容器启动的,它将工作...
另一个例子是通过 OAuth GitLab 服务在 Jenkins 中进行身份验证,其中相同的 URL GitLab 身份验证需要 both 从外部和 Jenkins 内部可用容器。
那么我的问题是:如何配置 nginx-proxy 以将请求从一个容器代理到另一个容器?
我没有看到任何讨论这个问题的话题,我对这个问题的理解不够,无法在 nginx 配置上构建解决方案。
任何帮助将不胜感激。
BMitch,可能性很大,确实是iptables规则问题,而不是nginx-proxy配置错误。
table filter
的链 INPUT 的默认策略是 DROP
,并且没有对来自容器 IP (127.20.X.X).
所以为了记录,如果其他人遇到同样的问题,我会提供一些情况的细节。
为了从外部世界访问容器,Docker 在 PREROUTING 和 FORWARD 规则上设置规则以允许外部 IP 从主机 IP DNAT 到容器 IP。这些默认规则允许任何外部 IP,这就是为什么限制对容器的访问需要一些高级 iptables 自定义。
请参阅此 link 示例:http://rudijs.github.io/2015-07/docker-restricting-container-access-with-iptables/
但是如果你的容器需要访问主机资源(在主机上运行的服务,或者在我的例子中,一个 nginx-proxy 容器监听 HTTP/HTTPS 主机端口并代理到容器),你需要采取关心 INPUT 链的 iptables 规则。
实际上,来自容器并发往主机的请求将由 Docker 守护程序路由到主机网络堆栈,但是 将需要传递 INPUT 链(因为请求 src
IP 是主机一个)。所以如果你想保护主机资源,让容器访问它们,不要记得添加这样的东西:
iptables -A INPUT -s 127.20.X.X/24 -j ACCEPT
其中 127.20.X.X/24 是您的容器所在的虚拟网络 运行.
非常感谢您的帮助。