粉丝服务

如何使用docker-gen为Docker容器自动化nginx代理

nginx-proxy设置一个运行nginx和docker-gen的容器。docker-gen为nginx生成反向代理配置,并在启动和停止容器时重新加载nginx。

用法

要运行它:

$ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

然后启动您想用env var代理的任何容器 VIRTUAL_HOST=subdomain.youdomain.com

$ docker run -e VIRTUAL_HOST=foo.bar.com ...

被代理必须在容器暴露的端口被代理,或者通过使用EXPOSE在他们的指令Dockerfile或使用--expose标志docker run或docker create。

如果您的DNS设置为将foo.bar.com转发到运行nginx-proxy的主机,则该请求将路由到具有VIRTUAL_HOST env var set的容器​​。

图像变体

nginx-proxy图像有两种版本。

jwilder / nginx的代理:最新

此图像使用debian:基于jessie的nginx图像。

$ docker pull jwilder/nginx-proxy:latest

jwilder / nginx的代理:高山

此图像基于nginx:alpine图像。使用此图片完全支持HTTP / 2(包括最近Chrome版本所需的ALPN)。还需要有效的证书(有关详细信息,请参阅“使用letsencrypt的SSL支持”下方)。

$ docker pull jwilder/nginx-proxy:alpine

Docker撰写

IPv6支持

您可以通过将值传递true给ENABLE_IPV6环境变量来激活对nginx-proxy容器的IPv6支持:

$ docker run -d -p 80:80 -e ENABLE_IPV6=true -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

多个端口

如果容器公开多个端口,则nginx-proxy将默认为在端口80上运行的服务。如果需要指定其他端口,则可以设置VIRTUAL_PORT env var以选择其他端口。如果您的容器仅暴露一个端口并且它具有VIRTUAL_HOST env var set,则将选择该端口。

多个主机

如果需要为容器支持多个虚拟主机,则可以使用逗号分隔每个条目。例如foo.bar.com,baz.bar.com,bar.com每台主机的设置都相同。

通配符主机

您还可以在主机名的开头和结尾使用通配符,例如*.bar.com或foo.bar.*。甚至是正则表达式,可以与像一个通配符DNS服务结合非常有用xip.io,使用~^foo.bar..*.xip.io匹配foo.bar.127.0.0.1.xip.io,foo.bar.10.0.2.2.xip.io和所有其他给定的IP。有关此主题的更多信息可以在nginx文档中找到server_names。

多个网络

通过在Docker 1.9中添加覆盖网络,您的nginx-proxy容器可能需要连接到多个网络上的后端容器。默认情况下,如果--net在nginx-proxy创建容器时未传递该标志,则它将仅附加到默认bridge网络。这意味着它将无法连接到除网络之外的网络上的容器bridge。

如果希望将nginx-proxy容器连接到其他网络,则必须--net=my-network在docker create或docker run命令中传递该选项。在撰写本文时,只能在容器创建时指定单个网络。要连接到其他网络,可以docker network connect在创建容器后使用该命令:

$ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro

--name my-nginx-proxy --net my-network jwilder / nginx-proxy

$ docker network连接my-other-network my-nginx-proxy

在此示例中,my-nginx-proxy容器将连接到my-network并且my-other-network将能够代理连接到这些网络的其他容器。

互联网与本地网络访问

如果您允许来自公共互联网的流量访问您的nginx-proxy容器,您可能希望仅将某些容器限制到内部网络,因此无法从公共互联网访问它们。在应限制为内部网络的容器上,应设置环境变量NETWORK_ACCESS=internal。默认情况下,内部网络定义为127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16。要更改被视为内部网络的网络列表,请在nginx-proxyat处/etc/nginx/network_internal.conf使用这些内容安装文件,根据您的需要进行编辑:

启用内部访问时,外部客户端被拒绝 HTTP 403 Forbidden

如果前面有负载平衡器/反向代理nginx-proxy隐藏客户端IP(例如:AWS Application / Elastic Load Balancer),则需要使用nginx realip模块(已安装)从HTTP请求中提取客户端的IP头。有关更多详细信息,请参阅nginx realip模块配置。可以将此配置添加到新配置文件并装入/etc/nginx/conf.d/。

SSL后端

如果您希望反向代理使用HTTPS而不是HTTP连接到您的后端,请VIRTUAL_PROTO=https在后端容器上设置。

注意:如果您使用VIRTUAL_PROTO=https并且您的后端容器公开端口80和443,nginx-proxy将在端口80上使用HTTPS。这几乎肯定不是您想要的,因此您还应该包括VIRTUAL_PORT=443。

uWSGI后端

如果要连接到uWSGI后端,请VIRTUAL_PROTO=uwsgi在后端容器上设置。然后,您的后端容器应该侦听端口而不是套接字并公开该端口。

FastCGI后端

如果要连接到FastCGI后端,请VIRTUAL_PROTO=fastcgi在后端容器上设置。然后,您的后端容器应该侦听端口而不是套接字并公开该端口。

FastCGI Filr根目录

如果使用fastcgi,则可以设置VIRTUAL_ROOT=xxx 根目录

默认主机

要设置nginx的默认主机,请使用env var DEFAULT_HOST=foo.bar.com作为示例

$ docker run -d -p 80:80 -e DEFAULT_HOST=foo.bar.com -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

独立的容器

nginx-proxy也可以使用jwilder / docker-gen 图像和官方nginx图像作为两个单独的容器运行。

您可能希望这样做以防止将docker套接字绑定到公开的容器服务。

您可以使用docker-compose演示此模式:

$ docker-compose --file docker-compose-separate-containers.yml up

$ curl -H “ Host:whoami.local ” localhost

我是5b129ab83266

要将nginx代理作为单独的容器运行,您需要在主机系统上安装nginx.tmpl。

首先使用卷启动nginx:

$ docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx

然后使用共享卷和模板启动docker-gen容器:

$ docker run --volumes-from nginx

-v /var/run/docker.sock:/tmp/docker.sock:ro

-v $(pwd):/etc/docker-gen/templates

-t jwilder/docker-gen -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf

最后,使用VIRTUAL_HOST环境变量启动容器。

$ docker run -e VIRTUAL_HOST=foo.bar.com ...

使用letsencrypt的SSL支持

letsencrypt-nginx-proxy-companion是nginx-proxy的轻量级伴随容器。它允许自动创建/续订Let的加密证书。

将DHPARAM_GENERATION环境变量设置为false完全禁用Diffie-Hellman参数。这也将忽略自动生成nginx-proxy。默认值为true

$ docker run -e DHPARAM_GENERATION=false ....

SSL支持

使用单主机,通配符和SNI证书支持SSL,使用证书的命名约定或可选地将证书名称(对于SNI)指定为环境变量。

要启用SSL:

$ docker run -d -p 80:80 -p 443:443 -v /path/to/certs:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

内容/path/to/certs应包含正在使用的任何虚拟主机的证书和私钥。证书和密钥应以具有.crt和 .key扩展名的虚拟主机命名。例如,一个容器VIRTUAL_HOST=foo.bar.com应该在certs目录中有一个 foo.bar.com.crt和foo.bar.com.key文件。

如果您在虚拟化环境(Hyper-V,VirtualBox等)中运行容器,则/ path / to / certs必须存在于该环境中或可供该环境访问。默认情况下,Docker无法将主机上的目录装载到虚拟机中运行的容器。

Diffie-Hellman群

默认情况下启用Diffie-Hellman组,其中包含预生成的密钥/etc/nginx/dhparam/dhparam.pem。您可以dhparam.pem在该位置安装其他文件以覆盖默认证书。要使用dhparam.pem每个虚拟主机的自定义文件,应在具有dhparam后缀和.pem扩展名的虚拟主机之后命名文件 。例如,一个容器VIRTUAL_HOST=foo.bar.com 应该foo.bar.com.dhparam.pem在/etc/nginx/certs目录中有一个文件。

注意:如果您没有安装dhparam.pem文件/etc/nginx/dhparam/dhparam.pem,将在启动时生成一个文件。由于生成新的可能需要几分钟dhparam.pem,因此在后台以低优先级完成。生成完成后,将dhparam.pem保存在持久卷上并重新加载nginx。此生成过程仅在您第一次启动时发生nginx-proxy。

兼容性警告:dhparam.pemA +安全性的默认生成密钥为2048位。一些较旧的客户端(如Java 6和7)不支持超过1024位的DH密钥。为了支持这些客户端,您必须提供自己的dhparam.pem,或者说nginx-proxy通过将产生在启动一个1024位的密钥-e DHPARAM_BITS=1024。

在单独的容器设置中,没有预生成的密钥可用,并且 jwilder / docker-gen图像和正式 nginx图像都不会生成一个。如果您仍然希望在单独的容器设置中使用A +安全性,则必须手动生成2048位DH密钥文件并将其安装在nginx容器上,at /etc/nginx/dhparam/dhparam.pem。

通配符证书

通配符证书和密钥应以带有.crt和.key扩展名的域名命名。例如,VIRTUAL_HOST=foo.bar.com将使用证书名称bar.com.crt和bar.com.key。

SNI

如果您的证书支持多个域名,则可以启动容器CERT_NAME=<name> 以标识要使用的证书。例如,证书*.foo.com和*.bar.com 可以命名shared.crt和shared.key。容器与运行VIRTUAL_HOST=foo.bar.com ,并CERT_NAME=shared随后将使用此共享证书。

OCSP Stapling

要为域启用OCSP Stapling,请nginx-proxy查找包含可信CA证书链的PEM证书/etc/nginx/certs/<domain>.chain.pem,其中<domain>是VIRTUAL_HOST指令中的域名。此文件的格式是公共PEM CA证书的串联,从最靠近SSL证书的中间CA开始,一直到根CA. 这通常被称为“SSL证书链”。如果找到,则将此文件名传递给NGINX ssl_trusted_certificate指令 并启用OCSP Stapling。

SSL支持如何工作

默认的SSL密码配置基于Mozilla中间配置文件,该配置文件应提供与Firefox 1,Chrome 1,IE 7,Opera 5,Safari 1,Windows XP IE8,Android 2.3,Java 7的客户端的兼容性。请注意,DES-基于TLS密码的安全性已被删除。该配置还支持HSTS,PFS,OCSP装订和SSL会话缓存。目前支持TLS 1.0,1.1和1.2。TLS 1.0已被弃用,但它的使用寿命截止日期为2018年6月30日。它被包含在内,因为以下浏览器在删除后将停止工作:Chrome <22,Firefox <27,IE <11,Safari <7,iOS <5,Android浏览器<5。

如果您不需要向后兼容性,则可以 通过将环境变量包含到容器中来使用Mozilla现代配置文件配置文件SSL_POLICY=Mozilla-Modern。此配置文件与客户端兼容,支持Windows 7,Edge,Opera 17,Safari 9,Android 5.0和Java 8上的Firefox 27,Chrome 30,IE 11。

可以通过其他政策SSL_POLICY环境变量是Mozilla-Old 和AWS ELB安全策略 AWS-TLS-1-2-2017-01,AWS-TLS-1-1-2017-01,AWS-2016-08,AWS-2015-05,AWS-2015-03和AWS-2015-02。

请注意,Mozilla-Old策略应使用1024位DH密钥以实现兼容性,但此容器会生成2048位密钥。在Diffie-Hellman组节详细绕过此不同的方法,无论是全球或每个虚拟主机。

暴露端口80和443时代理的默认行为如下:

  • 如果容器具有可用的证书,则端口80将重定向到该容器的443,以便在可用时始终首选HTTPS。
  • 如果容器没有可用的证书,则返回503。

请注意,在后一种情况下,浏览器可能会收到连接错误,因为没有可用于建立连接的证书。一个自签名或通用的证书default.crt,default.key 它将允许客户端浏览器建立SSL连接(可能带有警告)并随后接收500。

要在SSL和非SSL模式下提供流量而不重定向到SSL,您可以包含环境变量HTTPS_METHOD=noredirect(默认值为HTTPS_METHOD=redirect)。您也可以完全禁用非SSL站点HTTPS_METHOD=nohttp,或禁用HTTPS站点HTTPS_METHOD=nohttps。HTTPS_METHOD必须在要覆盖默认行为的每个容器上指定。如果HTTPS_METHOD=noredirect使用,则禁用严格传输安全性(HSTS)以防止HTTPS用户被客户端重定向。如果在更改此设置后无法访问HTTP站点,则浏览器可能已缓存HSTS策略并自动将您重定向回HTTPS。您需要清除浏览器的HSTS缓存或使用隐身窗口/其他浏览器。

默认情况下,为HTTPS站点 启用HTTP严格传输安全性(HSTS)max-age=31536000。您可以使用环境变量禁用HSTS,也可以 HSTS=off使用自定义HSTS配置HSTS=max-age=31536000; includeSubDomains; preload。

警告:HSTS会强制您的用户访问您网站的HTTPS版本max-age- 即使他们http://手动输入。收到HSTS响应后进入HTTP站点的唯一方法是清除浏览器的HSTS缓存。

基本认证支持

为了能够保护您的虚拟主机,您必须在目录/ etc / nginx / htpasswd / $ VIRTUAL_HOST上创建一个名为其等效VIRTUAL_HOST变量的文件。

$ docker run -d -p 80:80 -p 443:443

-v /path/to/htpasswd:/etc/nginx/htpasswd

-v /path/to/certs:/etc/nginx/certs

-v /var/run/docker.sock:/tmp/docker.sock:ro

jwilder/nginx-proxy

您需要在计划创建htpasswd文件的计算机上使用apache2-utils。请遵循这些说明

自定义Nginx配置

如果您需要使用环境变量超出可能的范围配置Nginx,则可以在代理范围或每个VIRTUAL_HOST基础上提供自定义配置文件。

替换默认代理设置

如果要替换nginx容器的默认代理设置,请在中添加配置文件/etc/nginx/proxy.conf。具有默认设置的文件如下所示:

注意:如果您提供此文件,它将替换默认值; 您可能需要检查.tmpl文件以确保您拥有所有必需的选项。

注意:默认配置阻止将ProxyHTTP请求标头发送到下游服务器。这可以防止攻击者使用所谓的 httpoxy攻击。有一个客户端发送这个头没有合法理由,而且有很多脆弱的语言/平台(CVE-2016-5385,CVE-2016-5386,CVE-2016-5387,CVE-2016-5388,CVE-2016-1000109,CVE-2016-1000110,CERT-VU#797896)。

代理范围

要在代理范围的基础上添加设置,请/etc/nginx/conf.d使用以...结尾的名称添加配置文件.conf。

这可以通过在RUN命令中创建文件或COPY将文件放入conf.d以下内容来在派生图像中完成:

来自 jwilder / nginx-proxy

RUN {

回声“server_tokens关闭;” ;

回声“client_max_body_size百米;” ;

} /etc/nginx/conf.d/my_proxy.conf

或者可以通过在docker run命令中安装自定义配置来完成:

$ docker run -d -p 80:80 -p 443:443 -v /path/to/my_proxy.conf:/etc/nginx/conf.d/my_proxy.conf:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

每VIRTUAL_HOST

要基于每个添加设置VIRTUAL_HOST,请在下面添加配置文件/etc/nginx/vhost.d。与代理范围的情况不同,它允许多个配置文件以任何名称结尾.conf,但VIRTUAL_HOST必须在完全命名之后命名VIRTUAL_HOST。

为了允许动态配置虚拟主机,因为添加和删除了后端,最适合安装外部目录,/etc/nginx/vhost.d而不是使用派生图像或安装单个配置文件。

例如,如果您有一个名为的虚拟主机app.example.com,则可以为该主机提供自定义配置,如下所示:

$ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

$ { echo 'server_tokens off;'; echo 'client_max_body_size 100m;'; } > /path/to/vhost.d/app.example.com

如果对单个容器使用多个主机名(例如VIRTUAL_HOST=example.com,www.example.com),则每个主机名必须存在虚拟主机配置文件。如果要对多个虚拟主机名使用相同的配置,可以使用符号链接:

$ { echo 'server_tokens off;'; echo 'client_max_body_size 100m;'; } > /path/to/vhost.d/www.example.com

$ ln -s /path/to/vhost.d/www.example.com /path/to/vhost.d/example.com

Per-VIRTUAL_HOST默认配置

如果您希望大多数虚拟主机使用默认的单个配置,然后覆盖几个特定的​​配置,请将这些设置添加到/etc/nginx/vhost.d/default文件中。此文件将用于任何没有/etc/nginx/vhost.d/{VIRTUAL_HOST}与之关联的文件的虚拟主机上。

Per-VIRTUAL_HOST位置配置

要在每个VIRTUAL_HOST基础上向“位置”块添加设置,请/etc/nginx/vhost.d 像上一节一样添加配置文件,但后缀除外_location。

例如,如果您有一个名为虚拟主机app.example.com且已my-cache在另一个自定义文件中配置了proxy_cache ,则可以告诉它使用代理缓存,如下所示:

$ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

$ { echo 'proxy_cache my-cache;'; echo 'proxy_cache_valid 200 302 60m;'; echo 'proxy_cache_valid 404 1m;' } > /path/to/vhost.d/app.example.com_location

如果对单个容器使用多个主机名(例如VIRTUAL_HOST=example.com,www.example.com),则每个主机名必须存在虚拟主机配置文件。如果要对多个虚拟主机名使用相同的配置,可以使用符号链接:

$ { echo 'proxy_cache my-cache;'; echo 'proxy_cache_valid 200 302 60m;'; echo 'proxy_cache_valid 404 1m;' } > /path/to/vhost.d/app.example.com_location

$ ln -s /path/to/vhost.d/www.example.com /path/to/vhost.d/example.com

Per-VIRTUAL_HOST位置默认配置

如果您希望大多数虚拟主机使用默认的单个location块配置,然后覆盖几个特定的​​配置,请将这些设置添加到/etc/nginx/vhost.d/default_location文件中。此文件将用于任何没有/etc/nginx/vhost.d/{VIRTUAL_HOST}_location与之关联的文件的虚拟主机上。

特约

在提交拉取请求或问题之前,请检查github以确保现有问题或拉取请求尚未打开。

在本地运行测试

要运行测试,您需要准备docker镜像以测试哪些必须标记jwilder/nginx-proxy:test:

docker build -t jwilder/nginx-proxy:test . # build the Debian variant image

并调用test / pytest.sh脚本。

然后构建图像的Alpine变体:

docker build -f Dockerfile.alpine -t jwilder/nginx-proxy:test . # build the Alpline variant image

并再次调用test / pytest.sh脚本。

如果您的系统具有该make命令,则可以通过调用以下命令自动执行这些任务:

make test

您可以在test / README.md文件中了解有关测试套件如何工作以及如何编写新测试的更多信息。

本栏目精选

热门推荐

频道导航