第 19 篇、凌晨 2 点被喊起来扩容?Docker Compose 水平扩展+负载均衡,30分钟搞定,不用K8s
摘要 本文针对Docker Compose水平扩展与负载均衡场景,提供了一套30分钟快速解决方案。文章首先剖析了Docker Compose内置DNS服务发现的负载均衡原理,随后详细列出了8个新手常见致命坑点及其解决方案,包括命令版本混用、Nginx DNS配置缺失等问题。最后通过实战演示,展示了如何仅用Docker Compose原生能力实现服务扩容,无需K8s集群或付费负载均衡器。文中提供了完
文章目录
第 19 篇、凌晨 2 点被喊起来扩容?Docker Compose 水平扩展+负载均衡,30分钟搞定,不用K8s

凌晨 2 点,部门群里:
“ @全员:测试压测把接口打崩了,单容器 QPS 到顶,用户访问直接 502,10 分钟内必须扩容恢复。”
你盯着屏幕,脑子一片空白。现在,真到要扩容的时候,可完全不知道从哪下手;
别慌,今天这篇文章,就带你用 Docker Compose 原生能力,30 分钟搞定水平扩展 + 负载均衡。
不用 K8s 集群,不用付费 SLB。零基础复制粘贴就能跑通,连运维小白都能直接落地。
【本文适配 Docker Compose V2 官方最新版本】
本文是《Docker 实战》系列第 19篇,全系列文章覆盖 Docker 基础、容器、镜像、仓库、网络核心实战,再到数据持久化、Dockerfile、Docker Compose 全场景落地,全程保姆级实战教学。
文末还给大家准备了专属新手福利:我亲手整理的**《Docker Compose 生产级最佳实践手册》+ 《10 套开箱即用 Compose 配置文件》。**
先搞懂核心原理
很多新手搞不懂,为什么 Docker Compose 不用额外配置就能实现负载均衡?
核心就两个知识点,看完你就通透了。
1. 什么是水平扩展?
垂直扩展:给单容器加 CPU / 内存(相当于给电脑换更大的内存条),上限低、成本高,很容易触顶
水平扩展:增加服务的容器实例数(相当于多开几台电脑一起干活),弹性强、成本可控,也是本文要讲的核心能力
2. Docker Compose 负载均衡的底层逻辑:内置 DNS 服务发现
Docker Compose 会给同一个服务的所有容器,分配同一个服务名(比如 flask),内置的 DNS 服务器会把这个服务名,轮询解析到所有后端容器的 IP 上。
简单说:你只要访问服务名,Docker 会自动把请求分给不同的容器,天生就带负载均衡能力,不用额外装任何组件。
新手必踩的 8 个致命坑
坑 1:命令版本混用
❌ 错误写法:混用旧版docker-compose(带横杠)和新版docker compose(空格)
✅ 正确方案:统一用官方标准docker compose(空格),2023 年起 Docker 已彻底废弃 V1 旧版
⚠️ 风险说明:旧命令复制后直接报错,新手找不到问题根源,白白浪费时间
坑 2:scale 命令缺参数
❌ 错误写法:docker compose up scale flask=3(少了--)
✅ 正确方案:docker compose up --scale 服务名=实例数 -d(比如--scale flask=3)
⚠️ 风险说明:语法错误导致命令执行失败,以为是环境问题,实则只是少个符号
坑 3:清理命令太暴力
❌ 错误写法:docker container rm -f $(docker container ps -aq)(删除所有容器)
✅ 正确方案:仅清理当前项目:docker compose down -v --rmi local
⚠️ 风险说明:会删除主机上所有容器(不管是不是当前项目的),新手执行直接 “翻车”,误删其他服务
坑 4:Nginx 缺 DNS 配置
❌ 错误写法:Nginx 直接写proxy_pass http://flask:5000;,不配置 DNS
✅ 正确方案:加 Docker 内置 DNS 配置:resolver 127.0.0.11 valid=5s;(5 秒刷新解析)
⚠️ 风险说明:Nginx 默认永久缓存 DNS,扩容新容器后不更新 IP,负载均衡完全不生效
很多朋友反馈:加了 resolver,负载均衡还是失效。
核心是没做动态上游 + 故障自动剔除,扩容新容器不识别、宕机还在转发请求,最终还是用户 502、线上背锅。
📌 【付费专属内容】给你 100 + 项目验证过的 Nginx 动态上游完整配置,复制即用,彻底解决这个生产死穴。
👉 这个方案的完整踩坑笔记和更新动态,我会同步更新,有需要可以文末找我。
坑 5:服务网络隔离错
❌ 错误写法:Nginx 和业务服务分属不同网络,业务服务没加双网络
✅ 正确方案:被 Nginx 访问的服务,需同时加入 “前端网络” 和 “后端网络”(比如 flask 加frontend-network+backend-network)
⚠️ 风险说明:Nginx 访问不到业务容器,用户访问直接返回 502,排查半天找不到网络问题
坑 6:启动依赖没配条件
❌ 错误写法:只写depends_on: - flask,不配置启动条件
✅ 正确方案:补充健康检查依赖:depends_on: {flask: {condition: service_healthy}}
⚠️ 风险说明:只会等容器启动,不会等服务就绪(比如 flask 还没跑起来,Nginx 就启动了),直接返回 502
坑 7:没加健康检查
❌ 错误写法:服务配置里完全没有healthcheck字段
✅ 正确方案:给所有服务加健康检查,比如 flask:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000"]
interval: 5s
timeout: 2s
retries: 3
⚠️ 风险说明:Docker 会把请求转发到已挂掉的容器,用户频繁看到 502,还以为是负载均衡配置错了
**提醒大家:**基础健康检查,只能识别容器状态,没法自动重启、异常告警。
凌晨容器崩了没人管,等用户投诉到老板那,你才被叫醒救火,太被动。
📌 【付费专属内容】给你生产级高可用自愈方案,自动重启 + 多平台告警配置,不用 24 小时人工盯守。
👉 这个方案的完整踩坑笔记和更新动态,我会同步更新,有需要可以文末找我。
坑 8:build 和 image 配置混淆
❌ 错误写法:以为build和image二选一,写了image就删build
✅ 正确方案:同时写是 “构建后打标签”,必须保留build(比如构建 flask 镜像并标为flask-demo:latest)
⚠️ 风险说明:没build字段会跳过镜像构建,直接拉取同名公共镜像,服务启动后完全不是自己要的功能
实战 1(极简版):内置 DNS 轮询,无 Nginx
关于 Docker 基础、容器、镜像、仓库、网络核心实战,再到数据持久化、Dockerfile、Docker Compose 全场景落地的更多高频坑,我都整理在了《Docker 实战》系列文章里。
关注 我「王二哥的技术笔记」:
- 查看往期全系列文章。
- 及时接收最新更新文章。
私信我,发送关键词【Compose】,即可直接领取全套资料。
适合内网测试、快速验证扩容效果,零额外依赖,复制就能跑。
步骤 1:环境准备
确保安装官方最新版本:
- Docker Engine ≥ 20.10
- Docker Compose V2
验证命令:
docker --version
docker compose version
步骤 2:项目结构与配置文件
创建项目目录,结构如下:
compose-scale-demo/
├── docker-compose.yml
└── flask/
├── Dockerfile
└── app.py
- 先写
flask/app.py(用来返回容器 ID,验证负载均衡效果)
from flask import Flask
from redis import Redis
import os
app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', 'redis-server'), port=6379)
@app.route('/')
def hello():
count = redis.incr('hits')
hostname = os.uname()[1] # 获取容器ID(容器的hostname就是容器ID)
return f'Hello World! 我被访问了 {count} 次,当前处理容器ID:{hostname}\n'
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)
- 再写
flask/Dockerfile(业务镜像构建文件)
FROM python:3.9.5-slim
RUN pip install flask redis && \
groupadd -r flask && useradd -r -g flask flask && \
mkdir /src && \
chown -R flask:flask /src
USER flask
COPY app.py /src/app.py
WORKDIR /src
ENV FLASK=app.py REDIS_HOST=redis
EXPOSE 5000
CMD ["flask", "run", "-h", "0.0.0.0"]
- 核心
docker-compose.yml
services:
flask:
build:
context: ./flask
dockerfile: Dockerfile
image: flask-demo:latest
environment:
- REDIS_HOST=redis-server
redis-server:
image: redis:latest
client:
image: xiaopeng163/net-box:latest
command: sh -c "while true; do sleep 3600; done;"
步骤 3:启动服务,验证基础状态
# 进入项目目录
cd compose-scale-demo
# 构建镜像+后台启动服务
docker compose up -d --build
# 查看服务状态,确保所有服务都是healthy状态
docker compose ps
步骤 4:水平扩展服务
# 把flask服务从1个实例,一键扩展到3个实例
docker compose up --scale flask=3 -d
# 再次查看状态,会看到3个flask容器,全部为healthy
docker compose ps
步骤 5:验证负载均衡效果
进入 client 容器,多次访问 flask 服务,观察返回的容器 ID:
# 进入client容器终端
docker compose exec client bash
# 多次访问,验证负载均衡
curl http://flask:5000
✅ 预期结果:每次返回的容器 ID 都不一样,说明 Docker 内置 DNS 已经实现了轮询负载均衡,水平扩展成功!
步骤 6:缩容服务
# 把flask服务一键缩容到1个实例
docker compose up --scale flask=1 -d
实战 2(Nginx 版):添加 Nginx 反向代理
适合对外暴露服务、需要高级负载策略的场景,适用于生产环境。
步骤 1:更新项目结构
compose-scale-demo/
├── docker-compose.yml
├── flask/
│ ├── Dockerfile
│ └── app.py
└── nginx/
└── nginx.conf
步骤 2:更新 docker-compose.yml(添加 Nginx )
services:
# 省略其他。。。
# 添加Nginx反向代理:对外入口,七层负载均衡
nginx:
image: nginx:stable-alpine
ports:
- "8000:80" # 对外暴露8000端口,可自行修改为80
volumes:
# 只读挂载配置文件,提升安全性
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- frontend-network
# 启动依赖:等flask服务完全就绪,再启动nginx,避免启动时502
depends_on:
flask:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:80/health"]
interval: 10s
timeout: 5s
retries: 3
步骤 3:添加 Nginx 配置
nginx/nginx.conf:
server {
listen 80 default_server;
location / {
proxy_pass http://flask:5000;
}
}
步骤 4:启动服务,验证效果
# 启动服务
docker compose up -d --build
# 一键扩展flask到3个实例
docker compose up --scale flask=3 -d
# 查看服务状态,确保所有服务healthy
docker compose ps
✅ 验证方式:
-
浏览器访问
http://你的服务器IP:8000,多次刷新,页面显示的容器 ID 会不断变化 -
本地多次执行 curl 命令验证:
curl http://localhost:8000 -
查看 Nginx 日志,确认请求被分发到不同容器:
docker compose logs -f nginx
现在,你能手动扩容了,但生产更新镜像 / 改代码,一重启就 502,用户流失、老板问责。
不用硬上复杂的 K8s,Docker Compose 原生就能搞定。
📌 【付费专属内容】带你 1 分钟实现零停机滚动更新,含完整配置 + 失败回滚兜底方案,中小项目直接落地。
👉 这个方案的完整踩坑笔记和更新动态,我会同步更新,有需要可以文末找我。
写在最后
新手专属福利
为了帮大家更快上手 Docker,我给大家整理了专属资料,都是我自己生产环境在用、新手能直接抄的实战内容:
- 《Docker Compose 生产级最佳实践》:包含了生产部署核心原则、官方标准做法、避坑红线,零基础也能直接落地
- Docker官方维护**《10套开箱即用Compose配置文件》**:覆盖 Python / NGINX / MySQL等主流技术栈,可直接复制到生产环境使用
- **《Docker 实战》**全系列避坑指南合集:覆盖网络、数据卷、镜像、编排全模块的 30 + 个新手高频坑,帮你少走半年弯路
资料领取方式:
私信我,发送关键词【Compose】,自动给你资料领取详情。
我会持续更新 Docker、云原生、Python 后端的实战干货,把我踩过的坑、总结的实战经验全部分享给你,帮你从入门到精通,少走弯路。
我们下期再见。
其他疑问
第 18 篇、凌晨 3 点还在排查 Docker 网络故障?Compose 容器通信玄学,90% 的坑都在这了
第 17 篇、凌晨 2 点还在更新 Docker 服务?Compose 越更越崩,90% 的坑都在这了
第 16 篇、90% Docker 新手都栽在这!Compose 镜像构建的 5 个致命坑,新手直接抄
第 15 篇、90% 的 Docker 新手都踩过的 8 个 Compose 坑!一文讲透核心逻辑,新手直接抄
Docker多容器环境,别瞎部署了!搞懂Compose,少走 90% 的弯路
相关内容我都给大家做好了,感兴趣的朋友来「我的主页」找一找,直接就可以看到。
欢迎关注 「王二哥的技术笔记」,每天分享「Docker」、「Python」、「FastAPI」、「Flask」有趣干货,千万不要错过!
更多推荐
所有评论(0)