本文目录导读:

配置容器补丁更新的Shell脚本需要考虑容器运行时的安全性、最小化停机时间和回滚能力,以下是几种常见场景的配置方案:
基础容器更新脚本(适用于测试环境)
#!/bin/bash
# 容器补丁更新脚本 - 基础版
set -euo pipefail
# 配置变量
CONTAINER_NAME="my-app"
IMAGE_NAME="my-registry/my-app"
BACKUP_DIR="/backup/containers"
LOG_FILE="/var/log/container-update.log"
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# 创建备份
backup_container() {
log "开始备份容器 $CONTAINER_NAME"
mkdir -p "$BACKUP_DIR"
# 导出当前容器配置
docker inspect "$CONTAINER_NAME" > "$BACKUP_DIR/${CONTAINER_NAME}_config_$(date +%Y%m%d_%H%M%S).json"
# 如果容器正在运行,创建镜像备份
if docker ps -q -f name="$CONTAINER_NAME" > /dev/null 2>&1; then
docker commit "$CONTAINER_NAME" "${IMAGE_NAME}:backup-$(date +%Y%m%d_%H%M%S)"
log "容器镜像备份完成"
fi
}
# 拉取最新镜像
pull_update() {
log "拉取最新镜像: $IMAGE_NAME:latest"
docker pull "$IMAGE_NAME:latest"
if [ $? -eq 0 ]; then
log "镜像拉取成功"
else
log "错误: 镜像拉取失败"
exit 1
fi
}
# 执行更新
perform_update() {
log "停止旧容器: $CONTAINER_NAME"
docker stop "$CONTAINER_NAME" || true
docker rm "$CONTAINER_NAME" || true
log "启动新容器"
docker run -d \
--name "$CONTAINER_NAME" \
--restart unless-stopped \
-p 8080:80 \
"$IMAGE_NAME:latest"
# 检查容器是否成功启动
sleep 5
if docker ps -q -f name="$CONTAINER_NAME" > /dev/null 2>&1; then
log "容器更新成功"
return 0
else
log "错误: 容器启动失败"
return 1
fi
}
# 健康检查
health_check() {
log "执行健康检查..."
# 替换为实际健康检查命令
curl -f http://localhost:8080/health || return 1
# 检查容器日志是否有错误
docker logs --tail 50 "$CONTAINER_NAME" | grep -i "error" && return 1
return 0
}
# 回滚函数
rollback() {
log "执行回滚操作..."
local backup_image=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep "${IMAGE_NAME}:backup" | sort | tail -1)
if [ -n "$backup_image" ]; then
docker stop "$CONTAINER_NAME" || true
docker rm "$CONTAINER_NAME" || true
docker run -d \
--name "$CONTAINER_NAME" \
--restart unless-stopped \
-p 8080:80 \
"$backup_image"
log "回滚完成,使用镜像: $backup_image"
else
log "没有找到可回滚的备份镜像"
exit 1
fi
}
# 主执行流程
main() {
log "开始容器补丁更新流程"
backup_container
pull_update
if perform_update; then
if health_check; then
log "更新成功完成"
else
log "健康检查失败,执行回滚"
rollback
fi
else
log "更新失败,执行回滚"
rollback
fi
}
# 执行
main
无停机更新脚本(蓝绿部署)
#!/bin/bash
# 蓝绿部署更新脚本
set -euo pipefail
# 配置变量
APP_NAME="my-app"
IMAGE="$1" # 从参数获取新镜像
BLUE_PORT=8081
GREEN_PORT=8082
ACTIVE_COLOR_FILE="/tmp/active_color.txt"
# 获取当前活跃环境
get_active_color() {
if [ -f "$ACTIVE_COLOR_FILE" ]; then
cat "$ACTIVE_COLOR_FILE"
else
echo "blue"
fi
}
# 切换负载均衡
switch_traffic() {
local new_color=$1
local new_port
if [ "$new_color" = "blue" ]; then
new_port=$BLUE_PORT
else
new_port=$GREEN_PORT
fi
# 更新负载均衡配置(示例使用Nginx)
cat > /etc/nginx/conf.d/${APP_NAME}.conf << EOF
upstream ${APP_NAME} {
server 127.0.0.1:${new_port};
}
server {
listen 80;
server_name ${APP_NAME}.example.com;
location / {
proxy_pass http://${APP_NAME};
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
}
}
EOF
nginx -s reload
echo "$new_color" > "$ACTIVE_COLOR_FILE"
echo "已切换到 $new_color 环境"
}
# 部署新版本到备用环境
deploy_staging() {
local active_color=$(get_active_color)
local staging_color
local staging_port
# 确定备用环境
if [ "$active_color" = "blue" ]; then
staging_color="green"
staging_port=$GREEN_PORT
else
staging_color="blue"
staging_port=$BLUE_PORT
fi
echo "部署到 $staging_color 环境"
# 启动新版本容器
docker run -d \
--name "${APP_NAME}-${staging_color}" \
-p ${staging_port}:80 \
"$IMAGE"
# 等待容器就绪
sleep 10
# 验证新版本
if curl -f http://localhost:${staging_port}/health; then
echo "新版本验证成功"
switch_traffic "$staging_color"
# 停止旧版本
docker stop "${APP_NAME}-${active_color}" || true
docker rm "${APP_NAME}-${active_color}" || true
else
echo "新版本验证失败,保持当前环境"
docker stop "${APP_NAME}-${staging_color}" || true
docker rm "${APP_NAME}-${staging_color}" || true
exit 1
fi
}
# 执行部署
deploy_staging
生产环境滚动更新脚本
#!/bin/bash
# 生产环境滚动更新脚本
set -euo pipefail
# 配置
CONTAINER_PREFIX="web-app"
INSTANCE_COUNT=3
IMAGE_NAME="$1"
ROLLBACK_IMAGE="${IMAGE_NAME}:previous"
# 滚动更新函数
rolling_update() {
local success_count=0
for i in $(seq 1 $INSTANCE_COUNT); do
local container_name="${CONTAINER_PREFIX}-${i}"
echo "更新容器 $container_name"
# 优雅停止
docker exec "$container_name" /usr/sbin/nginx -s quit || true
sleep 2
# 启动新容器
docker run -d \
--name "${container_name}_new" \
--network app-network \
"$IMAGE_NAME"
# 等待就绪
sleep 5
# 健康检查
if docker exec "${container_name}_new" curl -f http://localhost/health; then
# 切换流量
docker network disconnect app-network "$container_name" || true
docker network connect app-network "${container_name}_new"
# 停止旧容器
docker stop "$container_name" || true
docker rm "$container_name" || true
# 重命名新容器
docker rename "${container_name}_new" "$container_name"
((success_count++))
echo "容器 $container_name 更新成功"
else
echo "容器 ${container_name}_new 健康检查失败"
docker stop "${container_name}_new" || true
docker rm "${container_name}_new" || true
return 1
fi
done
echo "滚动更新完成,成功更新 $success_count/$INSTANCE_COUNT 个实例"
}
# 执行滚动更新
rolling_update
使用Docker Compose的更新脚本
#!/bin/bash
# Docker Compose更新脚本
set -euo pipefail
COMPOSE_FILE="docker-compose.yml"
PROJECT_NAME="my-project"
BACKUP_COMPOSE="docker-compose.backup.yml"
# 备份当前配置
backup_compose() {
echo "备份当前Docker Compose配置"
cp "$COMPOSE_FILE" "$BACKUP_COMPOSE"
# 保存当前镜像标签
docker-compose images > "images_backup_$(date +%Y%m%d).txt"
}
# 更新服务
update_services() {
echo "拉取最新镜像"
docker-compose pull
echo "重建并启动服务(零停机)"
docker-compose up -d --no-deps --build service1 service2
echo "等待服务就绪..."
sleep 10
# 健康检查
for service in service1 service2; do
if docker-compose ps "$service" | grep -q "Up"; then
echo "$service 运行正常"
else
echo "$service 启动失败,开始回滚"
rollback
exit 1
fi
done
}
# 回滚函数
rollback() {
echo "执行回滚..."
if [ -f "$BACKUP_COMPOSE" ]; then
cp "$BACKUP_COMPOSE" "$COMPOSE_FILE"
docker-compose down
docker-compose up -d
echo "回滚完成"
else
echo "没有可用的备份配置"
exit 1
fi
}
# 执行更新
backup_compose
update_services
自动化更新脚本(带通知和监控)
#!/bin/bash
# 完整的自动化更新脚本
set -euo pipefail
# 配置
NOTIFY_EMAIL="admin@example.com"
SLACK_WEBHOOK="https://hooks.slack.com/services/xxx"
PROMETHEUS_URL="http://prometheus:9090"
# 通知函数
notify() {
local message=$1
local level=${2:-INFO}
# 邮件通知
echo "$message" | mail -s "[$level] 容器更新通知" "$NOTIFY_EMAIL"
# Slack通知
curl -X POST -H "Content-Type: application/json" \
-d "{\"text\": \"[$level] $message\"}" \
"$SLACK_WEBHOOK" 2>/dev/null || true
}
# 监控指标检查
check_metrics() {
local query="avg(rate(container_cpu_usage_seconds_total[5m]))"
local result=$(curl -s "$PROMETHEUS_URL/api/v1/query?query=$query" | jq '.data.result[0].value[1]')
if (( $(echo "$result > 0.8" | bc -l) )); then
notify "CPU使用率过高: $result" "WARNING"
return 1
fi
return 0
}
# 预检查
pre_check() {
echo "执行更新前检查..."
# 检查磁盘空间
local disk_usage=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$disk_usage" -gt 80 ]; then
notify "磁盘使用率超过80%: $disk_usage%" "WARNING"
fi
# 检查内存
local mem_usage=$(free | grep Mem | awk '{print $3/$2 * 100.0}' | cut -d. -f1)
if [ "$mem_usage" -gt 80 ]; then
notify "内存使用率超过80%: $mem_usage%" "WARNING"
fi
# 检查当前容器状态
if ! docker ps --format "{{.Names}}" | grep -q "my-app"; then
notify "容器 my-app 不在运行状态" "ERROR"
exit 1
fi
echo "预检查通过"
}
# 后检查
post_check() {
echo "执行更新后检查..."
# 检查关键指标
check_metrics || true
# 检查API响应
local response_time=$(curl -o /dev/null -s -w "%{time_total}" http://localhost:8080/api/health)
if (( $(echo "$response_time > 2.0" | bc -l) )); then
notify "API响应时间过高: ${response_time}s" "WARNING"
fi
echo "后检查完成"
}
# 主流程
main() {
notify "开始容器更新流程" "INFO"
pre_check
# 执行更新(调用之前的更新函数)
if perform_update; then
post_check
notify "容器更新成功完成" "INFO"
else
notify "容器更新失败,开始回滚" "ERROR"
rollback
fi
}
# 执行主流程
main
使用建议
-
选择合适的更新策略:
- 测试环境:使用基础更新脚本
- 生产环境:使用蓝绿部署或滚动更新
- 高可用要求:使用滚动更新,逐个替换容器
-
安全考虑:
# 使用TLS验证镜像签名 export DOCKER_CONTENT_TRUST=1 # 使用只读文件系统 docker run --read-only ... # 限制容器资源 docker run --memory="512m" --cpus="0.5" ...
-
错误处理:
# 设置超时 timeout 120 docker-compose pull # 幂等性操作 docker stop container_name 2>/dev/null || true docker rm container_name 2>/dev/null || true
-
监控和日志:
# 发送更新事件到监控系统 curl -X POST "http://monitoring:8086/write?db=deployments" \ --data-binary "container_update,app=my-app,status=success value=1" # 集中日志收集 exec > >(tee -a /var/log/container-update.log | logger -t container-update)
定时更新脚本(cron示例)
# crontab -e # 每周日凌晨3点执行更新 0 3 * * 0 /usr/local/bin/container-update.sh >> /var/log/container-update.cron.log 2>&1 # 每天检查更新 0 0 * * * /usr/local/bin/check-updates.sh
选择哪种方案取决于你的具体需求:测试环境用简单方案,生产环境建议使用蓝绿部署或滚动更新,配合完整的监控和通知机制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播