未使用Docker Swarm时,Docker Compose扩缩容容器的负载均衡机制解析
问题描述
我用Docker Compose配置了包含Node.js应用和Nginx反向代理的两个服务,通过docker compose scale命令把Node容器扩到了3个。发现流量能在3个Node容器间实现负载均衡,但我没用到Docker Swarm,也没在文档里找到相关说明,想搞懂这个机制的实现原理。
附我的Nginx配置和docker ps -a输出:
Nginx配置
worker_processes auto; events { worker_connections 1024; } http { upstream all { server demo:80; } server { listen 80; location / { proxy_pass http://all; proxy_http_version 1.1; proxy_cache_bypass $http_upgrade; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection keep-alive; proxy_set_header Host $host; } } }
docker ps -a输出
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c6530cb5e017 demo-app "docker-entrypoint.s…" 13 hours ago Up 13 hours 0.0.0.0:49162->80/tcp, :::49162->80/tcp poc_demo_2 48b410882a89 demo-app "docker-entrypoint.s…" 13 hours ago Up 13 hours 0.0.0.0:49161->80/tcp, :::49161->80/tcp poc_demo_3 858feb84c60b demo-app "docker-entrypoint.s…" 13 hours ago Up 13 hours 0.0.0.0:49160->80/tcp, :::49160->80/tcp poc_demo_1 1a72a78ba820 nginx "nginx -g 'daemon of…" 13 hours ago Up 13 hours 0.0.0.0:80->80/tcp, :::80->80/tcp poc_nginx_1
调用Node接口时,每次响应来自不同容器,求解析这个负载均衡的实现方式。
实现原理解析
这个负载均衡是Docker Compose本地DNS服务发现+Nginx默认轮询策略共同作用的结果,和Docker Swarm完全无关,具体拆解:
Docker Compose的DNS自动解析
当你用Compose启动服务时,它会自动创建一个专属的桥接网络,所有服务容器都接入这个网络。Compose会为每个服务(比如你的demo服务)维护一个DNS条目,这个条目会自动关联该服务下所有运行中的容器IP——也就是说,当Nginx容器里访问demo:80时,Docker的DNS会返回3个Node容器的IP列表。Nginx的轮询负载均衡
Nginx启动时会解析demo域名,拿到所有对应的容器IP,把它们作为upstream集群的后端节点。Nginx默认的负载均衡策略是轮询(Round Robin),会按顺序把请求依次分配给各个后端容器,所以你会看到每次请求由不同容器响应。
补充:如果是运行中动态扩缩容,Nginx默认不会自动重新解析DNS,需要额外配置resolver开启动态解析,但你是先扩到3个容器再启动Nginx,所以启动时就已经拿到了完整的3个IP,直接生效。为什么不需要Swarm
Docker Swarm是跨节点的集群编排工具,负责多机器环境下的负载均衡,而你是单节点下的多容器场景,Compose自带的本地网络DNS服务发现就足够完成本地容器的流量分发,完全不需要依赖Swarm。
内容的提问来源于stack exchange,提问作者Atul

