背景
笔者在阿里云上有1台服务器,本着宁愿数据丢失也要榨干服务器的资源的目的,在那台服务器上启用了docker单节点集群,并且通过部署容器的方式开启了很多服务,比如
基础服务有 mysql、redis、rabbitmq、mongodb
应用服务包括 configserver、discovery 、springboot应用等
服务器本身应用也只是笔者在玩,并没有几个人访问,也没有什么请求量,所以负载均衡部分完全可以去掉,我要的只是大家共享80端口,而docker化的nginx需要一些配置文件,太过繁琐
目前使用的是阿里云针对容器的负载均衡slb,虽然使用的是最低配置的负载均衡实例,但每个月还是需要扣费差不多20元,对于笔者而言,花的这部分钱没有给我带来收益、也没有让我很爽,自然想要砍掉。接下来我们就看从技术上怎么去砍。
思路
前面也提到,我们不需要负载均衡,我们只要路由功能,受阿里云文档(自定义路由-使用手册_服务发现和负载均衡_Swarm 集群) 启发,我尝试使用 acs/proxy 镜像 但由于是基于 swarm 而我们的是swarm mode 自然行不通,后来也尝试过 dockercloud/haproxy 镜像也不行,
转机
终于在google中看到不少人推荐 jwilder/nginx-proxy 但是也没有v3版本的配置文件,但最终google告诉我 Centos7.4下用Docker-Compose部署WordPress(续) 我从中找到了v3版本的配置,终于可以删掉slb了,想想还有点小激动。
但是
当把服务部署上去发现依然不行,于是尝试找出不行的根源,测试被代理的应用,访问正常,那么问题应该是在nginx上,但以前没有玩过,于是简单看了一下文档,进去nginx容器中查看发现是这样
upstream dev.**.com {
## Can be connect with “multi-host-network” network
# springboot_web.1.1ss
server 10.1.0.8 down;
}
难道是健康检查没过,于是接着找原因,换了各种可能的关键词google才告诉我这篇文章 server down / VIRTUAL_PORT ignored · Issue #802 · jwilder/nginx-proxy 并紧接着在关联的 issue #1050 中找到可能解决的方案
——> 在dockerfile中加 EXPOSE [容器端口]
大概解释一下为什么会出现这种情况,当部署jwilder/nginx-proxy以后,nginx-proxy由于bug只能读取到dockerfile中定义的EXPOSE 所以在检测被代理的容器是否可用的时候就不能正确判断了,就会导致是down的状态,自然会导致502的情况了。可以放心的删除slb了
总结一下
- 需要在dockerfile中指定容器的端口才能被代理正确“上线”
- 需要部署jwilder/nginx-proxy 可以参考v3模板 需要提前创建好网络multi-host-network哦
version: ‘3.2’
services:
nginx:
image: jwilder/nginx-proxy:0.7.0
container_name: nginx-proxy
ports:
- “80:80”
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro #将宿主机的docker.sock绑定到nginx,这样,今后添加新的站点时,nginx将会自动发现站点并重启服务
restart: always
networks:
- multi-host-network
deploy:
restart_policy:
condition: on-failure
networks:
multi-host-network:
external: true
- 应用配置
version: ‘3.2’
services:
web:
image: 你的镜像地址
container_name: springbootweb
restart: always
ports:
- 80
labels:
aliyun.probe.initial_delay_seconds: ‘10’
aliyun.log_store_myblog: stdout
environment:
VIRTUAL_HOST: dev.*.com
networks:
- multi-host-network
deploy:
restart_policy:
condition: on-failure
networks:
multi-host-network:
external: true