开发者社区> 轩墨> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

为“多变”的Docker容器构建自动化的Nginx反向代理

简介: 本文讲的是为“多变”的Docker容器构建自动化的Nginx反向代理,【编者的话】Docker容器是无状态的,它们会随机分配IP和端口号。而在Web服务器中,我们经常需要适用Nginx来做负载均衡。众所周知,Nginx的配置需要制定主机IP和端口,那容器的IP、端口是变化的,这个时候我们应该如何配置了?作者给出了自己的解决方案,读者可以参考。
+关注继续查看
本文讲的是为“多变”的Docker容器构建自动化的Nginx反向代理【编者的话】Docker容器是无状态的,它们会随机分配IP和端口号。而在Web服务器中,我们经常需要适用Nginx来做负载均衡。众所周知,Nginx的配置需要制定主机IP和端口,那容器的IP、端口是变化的,这个时候我们应该如何配置了?作者给出了自己的解决方案,读者可以参考。需要注意的是,这种方案只适用于所有容器都在一台服务器上。

反向代理服务器通常是位于Web服务器的前端,它会提供一些Web服务器无法提供的附加功能。例如,一个反向代理服务器可以提供SSL、负载均衡、路由请求、缓存、压缩甚至A/B测试。

当在Docker容器中运行Web服务的时候,如果能在容器前运行一个反向代理服务器,那将会极大的简化部署流程。

-------------------------------------------------------------------------------------------------------------------------

为什么Docker要使用反向代理?

Docker容器会随机分配IP和端口号,所以从客户端寻找它们会变得异常复杂(译者注:比如你部署了一个Web服务,但每次重启后容器地址都会发生改变,这个时候你怎么去访问你的服务了?)。默认情况下,IP和端口号是专用于容器的,不能被外部访问,除非它们被绑定到主机上。

绑定容器到主机端口上的思路并不可行,它不便于在同一台主机运行多个容器。例如,在同一个时间内只能有一个容器可以绑定到80端口。同时这种方案也不利于扩展,因为在新容器开始之前,老容器必须停止。

反向代理可以帮助解决这些问题,也可以通过加快零死机时间部署来提高可用性。

-------------------------------------------------------------------------------------------------------------------------

生成反向代理配置

当容器开始和停止时,设置一个反向代理配置是非常复杂的。典型的配置都需要手动升级,但这个方式不仅容易出错,而且还很浪费时间。

幸运的是Docker提供了一个远程应用程序接口(API)来检查容器和它们的IP、端口和其它配置元数据。除此之外,也提供了一个实时事件API,当容器开始和停止的时候,可以发出实时通知。这些API都可以被用于自动生成一个反向代理配置。

docker-gen 是一个小程序,它可以使用这些API将容器元数据传递给模板,随之模板就可以重新生成,并通过一个可选择的通知指令来重启服务。

通过使用docker-gen,我们可以在重启改变的时候自动生成Nginx配置文件并重启。当然这些方法也可以用来管理Docker日志

-------------------------------------------------------------------------------------------------------------------------

用Docker建Nginx反向代理

下面例子中的这个Nginx模板可以为Docker容器生成一个反向代理配置,这个模板是使用golangtext/template package来实现的。它使用一个自定义的groupBy模板函数来对运行的容器进行分组(通过VIRTUAL_HOST环境变量)。这简化了遍历容器来生成一个负载均衡后端以及使得零停机部署变得可行。
{{ 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;
}
}

}}}

#### 试一试  我创建了一个[可信任的Docker镜像](https://index.docker.io/u/jwilder/nginx-proxy/)来做试验。 运行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 ...

如果你需要HTTPS,可能会喜欢在一个Nginx分组容器里运行docker-gen,需要Websocket支持或者其它特性,请在GitHub项目网站查看以获取更多信息。

-------------------------------------------------------------------------------------------------------------------------

结论

我们可以通过自动地使用Docker API和一些基本的模板来为Docker容器生成Nginx反向代理配置,这可以简化部署也可以提高可用性。

需要注意的是这种方案仅适用于单台机器,如果有多台机器可能就得考虑服务发现来生成配置了。如果你有兴趣,请查看Docker服务发现寻找解决问题的方法。

另外,这里有一些类似的观点值得你阅读:

原文链接:Automated Nginx Reverse Proxy for Docker (翻译:徐霞 校对: 吴锦晟)

原文发布时间为:2015-04-08
本文作者:吴锦晟 
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:为“多变”的Docker容器构建自动化的Nginx反向代理

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
LXJ
Docker 容器镜像删除
Docker 容器镜像删除
68 0
LXJ
docker从容器里面拷文件到宿主机或从宿主机拷文件到docker容器里面
docker从容器里面拷文件到宿主机或从宿主机拷文件到docker容器里面
161 0
LXJ
修改 Docker容器 自动启动/不自动启动
修改 Docker容器 自动启动/不自动启动
203 0
LXJ
docker容器备份和容器迁移
docker容器备份和容器迁移
80 0
容器存储架构比较:Kubernetes、Docker和Mesos Compare
本文讲的是容器存储架构比较:Kubernetes、Docker和Mesos Compare【编者的话】 容器存储是容器离不开的一个话题,对于无状态的Docker容器,容器重启时容器数据会自动清除,一些静态的数据我们可以通过配置文件或者在容器build时直接写死。
2662 0
容器简史:从20世纪70年代的chroot到2016的Docker
本文讲的是容器简史:从20世纪70年代的chroot到2016的Docker【编者的话】作者主要介绍了从1979年到2013年容器的发展史。
1793 0
Docker DevOps答疑:关于数据容器和网络
本文讲的是Docker DevOps答疑:关于数据容器和网络【编者的话】本文是Matt整理的DevOps vc见面会中一些互动问答,阅读本文Docker爱好者可以快速了解新特性和新趋势。
1443 0
容器、Docker与Kubernetes——Kubernetes的配置入门
本文讲的是容器、Docker与Kubernetes——Kubernetes的配置入门【编者的话】这是介绍Kubernetes的第三篇,主要集中讲述如何配置Kubernetes集群以及作者在配置过程中遇到的问题。
3203 0
容器、Docker与Kubernetes——从基础设施的容器化谈起
本文讲的是容器、Docker与Kubernetes——从基础设施的容器化谈起【编者的话】作者是Collective Idea公司的运维,也是个对技术有深度理解的人,这篇文章是作者在实践immutable infrastructure理念过程中对容器的理解,这是第一篇,主要讲述传统运维工具如Chef与Docker等容器化运维工具的不同以及解决的问题。
1232 0
容器、Docker与Kubernetes——什么是Kubernetes以及它是如何使得容器化基础设施变得简单
本文讲的是容器、Docker与Kubernetes——什么是Kubernetes以及它是如何使得容器化基础设施变得简单【编者的话】本文是系列文章第2篇,主要介绍Kubernetes。
1702 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
华为使用Docker支持系统容器的优化实践
立即下载
像搭积木一样玩转Docker的持续交付
立即下载
基于Docker on Yarn系统的微服务实践
立即下载