本文目录导读:

- 方案一:使用 Docker Compose + 脚本修改配置并重建(推荐)
- 方案二:直接更新正在运行的容器(Docker API / Systemd)
- 方案三:基于 CPU 使用率自动缩容(监控脚本)
- 方案四:使用 Docker Compose 的
scale命令(针对多副本服务) - 方案五:定时任务(Cron)实现夜间低负载缩容
- 重要注意事项
自动缩容 Docker 容器通常指减少容器资源限制(CPU、内存),而不是减少容器数量,因为容器本身是静态的,运行后无法直接修改其资源,所以需要通过更新容器配置或重建容器来实现。
以下是几种常见的自动化脚本方案,适用于不同场景:
使用 Docker Compose + 脚本修改配置并重建(推荐)
适用场景:容器由 Docker Compose 管理,需要按计划(如夜间)降低资源。
脚本思路:读取 docker-compose.yml,修改资源限制,然后执行 docker-compose up -d 重建。
示例脚本 (Bash):
#!/bin/bash # 定义缩容后的资源限制 NEW_MEMORY="512m" NEW_CPU="0.5" # 0.5核 # 要缩容的服务名称(在 docker-compose.yml 中定义) SERVICE_NAME="my-app" # 进入项目目录 cd /path/to/your/project echo "正在修改 docker-compose.yml..." # 使用 sed 替换资源限制(根据你的 YAML 格式调整) # 注意:如果启用了 deploy.resources,可能需要修改对应部分 sed -i "s/mem_limit: .*/mem_limit: $NEW_MEMORY/" docker-compose.yml sed -i "s/cpus: .*/cpus: $NEW_CPU/" docker-compose.yml echo "正在重新创建容器(缩容)..." docker-compose up -d --force-recreate $SERVICE_NAME echo "缩容完成!新资源限制:内存 $NEW_MEMORY, CPU $NEW_CPU"
直接更新正在运行的容器(Docker API / Systemd)
适用场景:容器由 docker run 直接创建,且容器进程支持运行时资源热调整(Docker 支持,但需要容器内有 cgroup 挂载)。
原理:使用 docker update 命令。
示例脚本:
#!/bin/bash
# 指定容器名或ID
CONTAINER_NAME="my-container"
# 缩容后的限制
NEW_MEMORY="256m"
NEW_CPU_SHARES="256" # CPU 权重,相对值
echo "正在热更新容器 ${CONTAINER_NAME} 的资源限制..."
docker update --memory=$NEW_MEMORY --cpu-shares=$NEW_CPU_SHARES $CONTAINER_NAME
# 验证
echo "当前限制:"
docker inspect $CONTAINER_NAME | grep -A 2 "Memory\|CpuShares"
基于 CPU 使用率自动缩容(监控脚本)
适用场景:根据容器实际负载自动调整(CPU > 80% 时缩容)。
示例脚本(Python):
#!/usr/bin/env python3
import subprocess
import json
import time
THRESHOLD_CPU = 80.0 # 触发缩容的CPU百分比
SCALE_DOWN_PERCENT = 0.7 # 缩容到当前资源的70%
def get_container_stats(container_id):
result = subprocess.run(
["docker", "stats", "--no-stream", "--format", "{{json .}}", container_id],
capture_output=True, text=True
)
if result.returncode != 0:
return None
try:
stats = json.loads(result.stdout.strip())
cpu_percent = float(stats["CPUPerc"].replace("%", ""))
mem_usage = stats["MemUsage"].split("/")[0].strip()
# 解析内存,"1.2GiB" -> 转换为字节
if "GiB" in mem_usage:
mem_bytes = float(mem_usage.replace("GiB", "")) * 1024**3
elif "MiB" in mem_usage:
mem_bytes = float(mem_usage.replace("MiB", "")) * 1024**2
else:
mem_bytes = float(mem_usage.replace("KiB", "")) * 1024
return cpu_percent, mem_bytes
except:
return None
def auto_scale_down(container_name):
print(f"监控容器: {container_name}")
while True:
stats = get_container_stats(container_name)
if stats:
cpu, mem = stats
print(f"当前 CPU: {cpu:.1f}%,内存: {mem/(1024**2):.1f} MiB")
if cpu > THRESHOLD_CPU:
new_mem = int(mem * SCALE_DOWN_PERCENT)
new_cpu_shares = int(1024 * SCALE_DOWN_PERCENT) # 1024 为默认
print(f"CPU 超限 ({cpu}%),正在缩容...")
subprocess.run([
"docker", "update",
"--memory", f"{new_mem}",
"--cpu-shares", str(new_cpu_shares),
container_name
])
print("缩容完成")
else:
print("无法获取容器统计信息")
time.sleep(60) # 每分钟检查一次
if __name__ == "__main__":
auto_scale_down("my-container")
使用 Docker Compose 的 scale 命令(针对多副本服务)
注意:这不是严格意义的“缩容”,而是减少容器副本数。
docker-compose up -d --scale my-service=1 # 将 my-service 缩容到 1 个副本
定时任务(Cron)实现夜间低负载缩容
在 /etc/cron.d/scale-down 中添加:
# 每天凌晨2点缩容
0 2 * * * root /usr/local/bin/scale-down.sh
重要注意事项
- 不可逆性:缩容操作需要回滚策略,如果缩容后业务负载回升,需要准备扩容器脚本。
- 内存限制:
docker update只对内存和 CPU 权重生效,无法热更新--cpus参数(需重启容器)。 - 容器内进程:如果容器内进程不响应
SIGTERM信号,直接--force-recreate会强杀。 - 建议使用编排工具:对于生产环境,更推荐使用 Kubernetes HPA(水平自动伸缩) 或 Docker Swarm 的 service update 进行资源管理。
推荐实践:如果只是简单环境,使用 方案二(docker update) 最快捷;如果需要复杂策略,用 方案三(Python监控) 结合 方案五(Cron)。