开发者社区> 轩墨> 正文
阿里云
为了无法计算的价值
打开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反向代理

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

相关文章
Docker 容器逃逸案例分析
## 0. 前言 本文参考自《Docker 容器与容器云》 这个容器逃逸的 case 存在于 Docker 1.0 之前的绝大多数版本。 目前使用 Docker 1.0 之前版本的环境几乎不存在了,这篇分析的主要目的是为了加深系统安全方面的学习。
9995 0
应用程序跑在Docker容器中会更安全
Docker对安全的支持是与生俱来的。作为一个平台,Docker为跑在其中的所有应用程序提供安全保障,不需要在Docker之外,单独部署一套安全解决方案。
1877 0
麻袋理财基于Docker的容器实践:互联网金融征信项目的微服务化之旅
本文转载自中生代技术群的分享,本期是FinTech第一期,本文将分享麻袋理财基于Docker的容器实践,带领大家走进互联网金融征信项目的微服务化之旅。
2663 0
为什么用Yarn来做Docker容器调度引擎
这篇文章是在一个微信群里和人聊天,然后整理出来的文字。当时Hulu推出了基于Yarn的Docker调度引擎。我正好那段时间也实现了一个类似的,经过交流,发现最后的实现基本是一致的。然而业界用的较多的是Mesos,这篇文章就是为了解释为什么选择用Yarn而不是Mesos来做。
2519 0
Docker的Windows容器初体验
最近微软发布了Windows Server 2016,其中最让广大开发者和运维同学期待的就是Docker对Windows容器的支持。如果你手边没有Windows Server 2016的环境,我们也可以在Windows 10 操作系统上,使用Docker for Windows来开始实验。
75173 0
【阿里云资讯】Docker首个国内合作商,阿里云何以认定容器技术将成主流?
10月13日,在2016杭州·云栖大会上,全球知名的容器技术公司Docker与阿里云宣布达成战略合作,双方将在容器服务领域进行紧密合作,阿里云称其将为客户提供更加先进的云上应用管理服务。双方称在开源容器技术以及其发展方向共同努力,为客户提供本地化Docker的企业级支持和咨询服务。
4339 0
【好书试读】Docker——容器与容器云(第2版)
本书根据Docker 1.10版和Kubernetes 1.2版对第1版进行了全面更新,从实践者的角度出发,以Docker和Kubernetes为重点,沿着“基本用法介绍”到“核心原理解读”到“高级实践技巧”的思路,一本书讲透当前主流的容器和容器云技术,有助于读者在实际场景中利用Docker容器和容
2131 0
实例解析Docker数据卷+数据卷容器+flocker数据共享+DockerHub操作
Docker内部数据管理和Docker之间的数据共享为数据卷和数据卷容器,实例解析1.将本地的文件作为容器的数据卷,2.数据卷flocker插件实现容器集群(或者Docker Swarm)的数据共享3.数据卷容器作为其他容器的数据卷.降低磁盘开销.4.数据的备份,恢复和迁移.5.Docker hub的常用操作. 1.0.数据卷(Data volumes) Data vol
1950 0
10张图带你深入理解Docker容器和镜像
打开微信扫一扫,关注微信公众号【数据与算法联盟】 转载请注明出处:http://blog.csdn.net/gamer_gyt 博主微博:http://weibo.com/234654758 Github:https://github.
1211 0
外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤。 1. 准备工作 1.1 安装并启动Docker容器 Docker容器默认的sshd端口是22。
2134 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
基于Docker on Yarn系统的微服务实践
立即下载
华为使用Docker支持系统容器的优化实践
立即下载
像搭积木一样玩转Docker的持续交付
立即下载