标签(空格分隔): Docker Nginx Automatedjavascript
本文做者是 jwilder,原文地址是 Automated Nginx Reverse Proxy for Dockercss
Docker 容器被分配随机 IP 和端口,这使得从客户端角度来寻址它们是很是复杂的。默认,IP 和端口是专用于主机的,而且不能被外部访问除非它们被绑定到主机上。html
绑定容器到主机端口能够防止多个容器在同一个主机上运行。好比,在同一时间仅仅只有一个容器能够被绑定到 80 端口。这也使得新版本的容器无停机的推出复杂化了,由于老版本必须在新版本启动以前先中止。java
一个反向代理能够帮助处理这些问题,同时经过减轻零停机部署的困难来提高可用性。nginx
当一个容器被启动和中止的时候,设置一个反向代理配置多是复杂的。一般的配置须要手动更新,这容易出错而且费时。git
幸运的是,Docker 提供了一个远程 API 来 inspect containers 和访问他们的 IP,端口和其余配置元数据。另外,它也提供一个实时事件 API能够被用于通知何时容器被启动和中止。这些 API 能够被用于自动地生成一个反向代理配置。github
docker-gen 是一个使用这些 API 的小工具,并导出容器的元数据到模板中。模板被渲染以及一个可选的通知命令能够被运行来重起服务。golang
使用 docker-gen,咱们能够自动的生成 Nginx 的配置并重载 Nginx当它们改变的时候。一样的方法可被用于 Docker 日志管理。web
这个例子 Nginx 模板能够被用于生成一个 Docker 容器使用虚拟主机路由的反向代理配置文件。这个模板是使用 golang text/template package 实现的。它使用一个通用的 groupBy
模板函数经过它们的 VIRTUAL_HOST
环境变量来分组运行的容器。这简化了遍历容器来生成一个负载均衡后端以及使得零停机部署可行。docker
{{ range $host, $containers := groupBy $ "Env.VIRTUAL_HOST" }} upstream {{ $host }} { {{ range $index, $value := $containers }} {{ with $address := index $value.Addresses 0 }} server {{ $address.IP }}:{{ $address.Port }}; {{ end }} {{ end }} } server { #ssl_certificate /etc/nginx/certs/demo.pem; #ssl_certificate_key /etc/nginx/certs/demo.key; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; server_name {{ $host }}; location / { proxy_pass http://{{ $host }}; include /etc/nginx/proxy_params; } } {{ end }}
这个模板可使用 docker-gen
来运行:
docker-gen -only-exposed -watch -notify "/etc/init.d/nginx reload" templates/nginx.tmpl /etc/nginx/sites-enabled/default
-only-exposed
- 仅仅使用容器已经暴露的端口。-watch
- 启动以后,监控 docker 容器事件和从新生成模板。-notify "/etc/init.d/nginx reload"
- 在模板生成后重载 nginx 配置。templates/nginx.tmpl
- nginx 模板。/etc/nginx/sites-enabled/default
- 目标文件。这是两个容器配置了 VIRTUAL_HOST=demo1.localhost
和 VIRTUAL_HOST=demo2.localhost
的渲染模板。
upstream demo1.localhost { server 172.17.0.4:5000; server 172.17.0.3:5000; } server { #ssl_certificate /etc/nginx/certs/demo.pem; #ssl_certificate_key /etc/nginx/certs/demo.key; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; server_name demo1.localhost; location / { proxy_pass http://demo.localhost; include /etc/nginx/proxy_params; } } upstream demo2.localhost { server 172.17.0.5:5000; } server { #ssl_certificate /etc/nginx/certs/demo.pem; #ssl_certificate_key /etc/nginx/certs/demo.key; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; server_name demo2.localhost; location / { proxy_pass http://demo2.localhost; include /etc/nginx/proxy_params; } }
我使用这个设置建立了一个可信任的构建来使得它很是容易试验。
运行 nginx-proxy 容器:
$ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock -t jwilder/nginx-proxy
使用一个 VIRTUAL_HOST
环境变量启动你的容器:
docker run -e VIRTUAL_HOST=foo.bar.com -t ...
为 docker 容器生成 nginx 反向代理配置能够经过使用 Docker APIs 和一些基础的模板自动化,这能够简化部署同时提高可用性。
虽然这很是适用于单台主机上运行的容器,为远程主机生成配置须要自动发现。看一下 Docker 自动发现 对这个问题的解决。
更新:这有一些相似观点和变种的其余文章值得一看: