脚本怎样批量启停管理容器

wen 实用脚本 33

从零到一的高效运维实战指南

目录导读

  1. 为什么需要批量管理容器?
    当容器数量超过两位数时,手动启停已成灾难,本文揭晓如何用脚本彻底解放生产力。

    脚本怎样批量启停管理容器

  2. 核心思路解析
    从容器状态识别、操作策略到脚本框架设计,建立全局认知。

  3. 基础脚本实例:批量停止/启动所有容器
    包含docker ps -a与条件过滤的完整代码及运行截图(示意图)。

  4. 进阶场景:按名称、标签、状态精准过滤
    利用docker inspectjq解析元数据,实现精准控制。

  5. 安全防护:命令执行前二次确认机制
    防止误操作导致生产环境瘫痪——read交互 + 模拟运行模式。

  6. 定时任务与异常处理
    结合crontab实现夜间自动启停,并捕获失败日志。

  7. 容器编排与脚本的取舍
    Docker Compose vs 原生脚本:何时选择脚本,何时需要编排工具。

  8. 常见问题(FAQ)

    • Q:脚本执行到一半报错怎么办?
    • Q:如何只重启状态异常的容器?
    • Q:Windows环境下能否运行这些脚本?

为什么需要批量管理容器?

在微服务架构或CI/CD流水线中,一个项目可能同时运行20~50个容器,如果每个都要手动执行docker startdocker stop,不仅效率低下,而且极易遗漏或误操作。

  • 夜间资源回收:开发环境在非工作时间关闭以节省服务器费用。
  • 版本升级:需要同时重启所有关联容器以加载新配置。
  • 故障快照:批量暂停所有容器后导出日志或镜像。

脚本化管理的三个优势

  • 可重复:同一脚本在任意环境执行相同逻辑。
  • 可审计:输出日志记录每一步操作。
  • 可扩展:轻松集成到监控或自动化平台。

核心思路解析

批量管理容器脚本的核心逻辑可归纳为三步:

获取容器列表 → 过滤目标容器 → 执行操作(start/stop/restart)

关键设计点

  • 状态识别:检查容器是runningexitedpaused等状态。
  • 操作幂等性:对已停止的容器执行stop不应报错,对已运行的容器执行start应跳过。
  • 错误隔离:单个容器失败不影响其他容器操作。

常见的过滤条件包括:容器名称前缀、标签(如env=dev)、镜像名称、运行时长等。


基础脚本实例:批量停止/启动所有容器

1 批量停止所有运行中的容器

#!/bin/bash
# stop_all_containers.sh
echo ">> 正在获取所有运行中的容器..."
RUNNING_CONTAINERS=$(docker ps -q)
if [ -z "$RUNNING_CONTAINERS" ]; then
    echo ">> 没有正在运行的容器。"
else
    echo ">> 即将停止以下容器:"
    docker ps --format "table {{.ID}}\t{{.Names}}" | tail -n +2
    echo ">> 开始停止..."
    docker stop $RUNNING_CONTAINERS
    echo ">> 所有运行中的容器已停止。"
fi

2 批量启动所有已停止的容器

#!/bin/bash
# start_all_stopped.sh
echo ">> 正在获取所有已停止的容器..."
STOPPED_CONTAINERS=$(docker ps -a -f "status=exited" -q)
if [ -z "$STOPPED_CONTAINERS" ]; then
    echo ">> 没有已停止的容器。"
else
    echo ">> 即将启动以下容器:"
    docker ps -a -f "status=exited" --format "table {{.ID}}\t{{.Names}}" | tail -n +2
    echo ">> 开始启动..."
    docker start $STOPPED_CONTAINERS
    echo ">> 所有已停止的容器已启动。"
fi

执行效果

  • stop_all_containers.sh 先列出所有运行中的容器ID和名称,然后逐一停止。
  • 即使部分容器已停止,docker stop也不会报错,实现幂等操作。

进阶场景:按名称、标签、状态精准过滤

当容器数量庞大(例如200+),且只有部分需要重启时,精准过滤至关重要。

1 按名称前缀重启

#!/bin/bash
# restart_by_prefix.sh
PREFIX="myapp-"
echo ">> 查找名称以 '$PREFIX' 开头的容器..."
CONTAINERS=$(docker ps -a --filter "name=^/${PREFIX}" -q)
if [ -z "$CONTAINERS" ]; then
    echo ">> 未找到匹配容器。"
    exit 0
fi
echo ">> 匹配到以下容器:"
docker ps -a --filter "name=^/${PREFIX}" --format "table {{.Names}}\t{{.Status}}"
echo ">> 重启中..."
docker restart $CONTAINERS
echo ">> 完成。"

2 按标签(Label)过滤后批量管理

#!/bin/bash
# manage_by_label.sh
LABEL="env=staging"
ACTION=${1:-stop}  # 默认操作为stop,可传参 start/stop/restart
echo ">> 查找标签为 '$LABEL' 的容器..."
CONTAINERS=$(docker ps -a --filter "label=$LABEL" -q)
if [ -z "$CONTAINERS" ]; then
    echo ">> 未找到匹配容器。"
    exit 0
fi
echo ">> 执行操作: $ACTION"
for CID in $CONTAINERS; do
    docker $ACTION $CID
done

使用方式
./manage_by_label.sh start./manage_by_label.sh stop

3 按状态过滤:只重启异常容器

#!/bin/bash
# restart_restarting.sh
echo ">> 查找状态为 restarting 的容器..."
RESTARTING=$(docker ps --filter "status=restarting" -q)
if [ -n "$RESTARTING" ]; then
    echo ">> 发现以下容器处于重启循环中:"
    docker ps --filter "status=restarting" --format "table {{.ID}}\t{{.Names}}"
    echo ">> 执行重启..."
    docker restart $RESTARTING
else
    echo ">> 无异常容器。"
fi

安全防护:命令执行前二次确认机制

误操作是运维大忌,以下脚本在执行前打印即将操作的容器列表,并要求用户输入yes确认。

#!/bin/bash
# batch_stop_with_confirm.sh
echo ">> 以下容器将被停止:"
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Image}}" | tail -n +2
read -p ">> 确认停止以上所有容器?(输入yes确认): " CONFIRM
if [ "$CONFIRM" != "yes" ]; then
    echo ">> 已取消操作。"
    exit 0
fi
echo ">> 停止中..."
docker stop $(docker ps -q)
echo ">> 操作完成。"

增强安全措施

  • 模拟运行模式:加入--dry-run参数,只打印命令而不实际执行。
  • 日志备份:操作前将容器状态导出到文件。
if [ "$1" == "--dry-run" ]; then
    echo ">> 模拟运行模式:"
    echo "   docker stop $(docker ps -q)"
    exit 0
fi

定时任务与异常处理

1 结合crontab实现夜间自动回收

假设你希望每天晚上23:00停止所有开发环境的容器,白天8:00启动:

# 编辑crontab:crontab -e
0 23 * * * /home/ops/stop_dev_env.sh >> /var/log/container_stop.log 2>&1
0 8 * * * /home/ops/start_dev_env.sh >> /var/log/container_start.log 2>&1

2 异常处理:捕获失败并发送告警

#!/bin/bash
# batch_stop_with_trap.sh
FAILED_CONTAINERS=()
STOP_LIST=$(docker ps -q)
for CID in $STOP_LIST; do
    docker stop $CID || FAILED_CONTAINERS+=("$CID")
done
if [ ${#FAILED_CONTAINERS[@]} -gt 0 ]; then
    echo ">> 以下容器停止失败:" >&2
    for CID in "${FAILED_CONTAINERS[@]}"; do
        docker ps -a --filter "id=$CID" --format "table {{.Names}}" | tail -n +2
    done
    # 可在此调用邮件或Slack接口告警
    exit 1
else
    echo ">> 所有容器停止成功。"
fi

容器编排与脚本的取舍

何时使用脚本?

  • 临时管理:一次性操作或不定期维护。
  • 非标准场景:如需要基于容器状态动态决策(例如先停止依赖链下游的容器)。
  • 环境兼容:裸机或混合环境,未使用编排工具。

何时使用Docker Compose或Kubernetes?

  • 长期运行的多服务应用:Compose的up/down天然支持批量启停。
  • 需要滚动更新、健康检查:Kubernetes的Deployment更可靠。
  • 声明式管理:配置即代码,避免脚本逻辑分散。

最佳实践
脚本适合作为“胶水代码”连接现有工具,

  • 在CI/CD流程中调用脚本更新特定标签的容器。
  • 在监控报警触发时自动重启异常容器。

常见问题(FAQ)

Q1:脚本执行到一半报错,部分容器已操作成功,如何回滚?

A:建议在操作前先保存当前容器状态快照:

docker ps --format "{{.ID}}:{{.Names}}" > /tmp/container_snapshot_$(date +%Y%m%d%H%M).txt

若出错,可手动恢复:对已停止的容器执行start,对已启动的容器执行stop,更稳健的方案是在脚本内添加“操作记录表”,每成功操作一个容器就记录,失败时反向恢复已操作部分。

Q2:如何只重启状态异常的容器(如不停重启的容器)?

A:使用过滤条件 --filter "status=restarting"--filter "status=exited",然后执行docker restart,示例参见4.3节。

Q3:Windows环境下(如Docker Desktop on Windows)能否运行这些脚本?

A:可以,Windows支持WSL2(Windows Subsystem for Linux),可在WSL2中直接运行bash脚本,或者使用PowerShell版本:

# Windows PowerShell 示例
$containers = docker ps -q
if ($containers) {
    docker stop $containers
}

推荐使用WSL2,因其与Linux环境完全兼容。

Q4:脚本如何避免操作到生产环境容器?

A

  • 环境变量隔离:在脚本中检查环境变量ENV,只有devstaging时才允许执行。
  • 标签硬限制:仅操作包含特定标签(如env=experimental)的容器。
  • 白名单机制:脚本内定义允许操作的容器名称列表。

示例:

ALLOWED_PREFIX="dev-"
CONTAINERS=$(docker ps -a --filter "name=^/${ALLOWED_PREFIX}" -q)
if [ -z "$CONTAINERS" ]; then echo "无匹配容器,退出。"; exit 0; fi

通过本文,你已掌握从基础到进阶的容器批量管理脚本编写方法,关键点在于:清晰过滤、幂等操作、安全确认、日志记录,无论你管理的是10个还是1000个容器,合理的脚本都能让启停操作变得可靠且可控。

本文所有示例脚本均经过基础测试,建议在生产环境部署前在测试环境验证。

抱歉,评论功能暂时关闭!