为“多变”的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反向代理
目录
相关文章
|
2月前
|
敏捷开发 测试技术 API
测试金字塔:构建高效自动化测试策略的基石
测试金字塔:构建高效自动化测试策略的基石
271 116
|
2月前
|
设计模式 前端开发 测试技术
告别脆弱:构建稳定UI自动化测试的3个核心策略
告别脆弱:构建稳定UI自动化测试的3个核心策略
344 113
|
2月前
|
应用服务中间件 网络安全 nginx
手把手教你使用 Docker 部署 Nginx 教程
本文详解Nginx核心功能与Docker部署优势,涵盖镜像拉取、容器化部署(快速、挂载、Compose)、HTTPS配置及常见问题处理,助力高效搭建稳定Web服务。
1105 4
|
2月前
|
JSON 监控 API
n8n错误处理全攻略:构建稳定可靠的自动化工作流
在n8n自动化工作流中,错误是提升系统可靠性的关键。本文详解常见错误类型、节点级与全局处理机制,结合重试、熔断、补偿事务等高级模式,助您构建稳定、可维护的生产级自动化流程。
|
2月前
|
测试技术 API 数据库
测试金字塔:构建高效自动化测试策略的基石
测试金字塔:构建高效自动化测试策略的基石
307 114
|
2月前
|
应用服务中间件 Linux nginx
在虚拟机Docker环境下部署Nginx的步骤。
以上就是在Docker环境下部署Nginx的步骤。需要注意,Docker和Nginix都有很多高级用法和细节需要掌握,以上只是一个基础入门级别的教程。如果你想要更深入地学习和使用它们,请参考官方文档或者其他专业书籍。
154 5
|
2月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
499 5
|
2月前
|
监控 Linux 调度
【赵渝强老师】Docker容器的资源管理机制
本文介绍了Linux CGroup技术及其在Docker资源管理中的应用。通过实例演示了如何利用CGroup限制应用程序的CPU、内存和I/O带宽使用,实现系统资源的精细化控制,帮助理解Docker底层资源限制机制。
236 6
|
2月前
|
Java 项目管理 Maven
Maven项目管理与构建自动化完全指南
Maven彻底改变了Java项目管理方式,通过POM模型、依赖管理和标准化构建流程,大幅提升开发效率。本文深入解析其核心概念、多模块管理、私服搭建及与Spring Boot、Docker等现代技术栈的集成实践,助力开发者实现高效、规范的项目构建与团队协作。
Maven项目管理与构建自动化完全指南