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

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本文讲的是为“多变”的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反向代理
目录
相关文章
|
1天前
|
Java 虚拟化 Docker
Docker简介及用途,为什么要使用Docker?Docker容器和虚拟机的区别
Docker简介及用途,为什么要使用Docker?Docker容器和虚拟机的区别
|
1天前
|
存储 Linux Docker
CentOS7修改Docker容器和镜像默认存储位置
CentOS7修改Docker容器和镜像默认存储位置
|
1天前
|
Linux Docker 容器
更改docker容器中的时间而不影响宿主机
更改docker容器中的时间而不影响宿主机
|
1天前
|
Ubuntu Linux Go
docker容器启动报错
docker容器启动报错解决
|
2天前
|
应用服务中间件 网络安全 Apache
构建高性能Web服务器:Nginx vs Apache
【5月更文挑战第16天】Nginx与Apache是两种主流Web服务器,各具优势。Nginx以其轻量级、高并发处理能力和反向代理功能见长,适合大型网站和高并发场景;而Apache以功能丰富、稳定性强闻名,适合企业网站和需要多种Web服务功能的场景。在性能上,Nginx处理高并发更优,Apache则可能在高负载时遭遇瓶颈。在选择时,应根据实际需求权衡。
|
3天前
|
运维 Kubernetes Devops
构建高效稳定的云基础设施:DevOps与容器化技术融合实践
【5月更文挑战第15天】 在当今的云计算时代,企业为了保持竞争力,不断寻求提高软件交付速度和服务质量的方法。本文将探讨如何通过结合DevOps原则和容器化技术来构建一个既高效又稳定的云基础设施。文章首先介绍了DevOps的核心概念及其如何促进开发与运维的协作,然后详细阐述了容器化技术如何优化应用部署和运行环境。最后,通过一个实际案例分析,展示了这种融合策略在提升自动化水平、加快部署速度以及增强系统稳定性方面的具体成效。
|
3天前
|
Ubuntu Docker 容器
docker容器保存和导入
docker容器保存和导入
20 0
|
3天前
|
Ubuntu Docker 容器
清理docker容器
清理docker容器
12 0
|
3天前
|
存储 安全 数据安全/隐私保护
【Docker 专栏】Docker 容器化应用的备份与恢复策略
【5月更文挑战第9天】本文探讨了Docker容器化应用的备份与恢复策略,强调了备份在数据保护、业务连续性和合规要求中的关键作用。内容涵盖备份的重要性、内容及方法,推荐了Docker自带工具和第三方工具如Portainer、Velero。制定了备份策略,包括频率、存储位置和保留期限,并详细阐述了恢复流程及注意事项。文章还提及案例分析和未来发展趋势,强调了随着技术发展,备份与恢复策略将持续演进,以应对数字化时代的挑战。
【Docker 专栏】Docker 容器化应用的备份与恢复策略
|
3天前
|
监控 Kubernetes Docker
【Docker 专栏】Docker 容器内应用的健康检查与自动恢复
【5月更文挑战第9天】本文探讨了Docker容器中应用的健康检查与自动恢复,强调其对应用稳定性和系统性能的重要性。健康检查包括进程、端口和应用特定检查,而自动恢复则涉及重启容器和重新部署。Docker原生及第三方工具(如Kubernetes)提供了相关功能。配置检查需考虑检查频率、应用特性和监控告警。案例分析展示了实际操作,未来发展趋势将趋向更智能和高效的检查恢复机制。
【Docker 专栏】Docker 容器内应用的健康检查与自动恢复