Containerized Application Lifecycle Management - Mastering the Full Application Journey
2025/8/31大约 9 分钟
容器化应用的生命周期管理
应用生命周期概述
容器化应用的生命周期管理涵盖了从应用开发到退役的完整过程。通过标准化和自动化的生命周期管理,可以提高应用的可靠性、可维护性和交付效率。
生命周期阶段
开发阶段:
- 应用开发和容器化
- 本地测试和调试
测试阶段:
- 单元测试、集成测试
- 性能测试和安全测试
部署阶段:
- 镜像构建和推送
- 环境部署和配置
运维阶段:
- 监控、日志和告警
- 扩缩容和更新
退役阶段:
- 资源清理和数据迁移
- 应用下线和归档
开发阶段管理
本地开发环境
# 开发环境 Dockerfile
FROM node:14
WORKDIR /app
# 安装开发工具
RUN npm install -g nodemon typescript ts-node
# 复制依赖文件
COPY package*.json ./
RUN npm install
# 复制源代码
COPY . .
# 暴露开发端口
EXPOSE 3000 9229
# 开发模式启动
CMD ["npm", "run", "dev"]# docker-compose.dev.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
- "9229:9229" # 调试端口
volumes:
- .:/app # 代码热重载
- /app/node_modules # 避免覆盖 node_modules
environment:
- NODE_ENV=development
- DEBUG=app:*
depends_on:
- db
- redis
db:
image: postgres:13
environment:
- POSTGRES_USER=dev
- POSTGRES_PASSWORD=dev
- POSTGRES_DB=myapp
volumes:
- db_data:/var/lib/postgresql/data
ports:
- "5432:5432"
redis:
image: redis:6-alpine
ports:
- "6379:6379"
volumes:
db_data:开发工具集成
# 开发环境脚本
#!/bin/bash
# dev-env.sh
echo "启动开发环境..."
# 构建开发镜像
docker-compose -f docker-compose.dev.yml build
# 启动开发环境
docker-compose -f docker-compose.dev.yml up -d
# 等待服务启动
echo "等待服务启动..."
sleep 10
# 运行数据库迁移
docker-compose -f docker-compose.dev.yml exec app npm run migrate
# 运行种子数据
docker-compose -f docker-compose.dev.yml exec app npm run seed
echo "开发环境已启动!"
echo "应用地址: http://localhost:3000"
echo "数据库: postgresql://dev:dev@localhost:5432/myapp"测试阶段管理
测试环境配置
# 测试环境 Dockerfile
FROM node:14-alpine
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
RUN npm ci --only=production
# 复制源代码
COPY . .
# 安装测试工具
RUN npm install --save-dev mocha chai supertest
# 暴露测试端口
EXPOSE 3000
# 运行测试
CMD ["npm", "test"]# docker-compose.test.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.test
environment:
- NODE_ENV=test
- DATABASE_URL=postgresql://test:test@db:5432/test
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
db:
image: postgres:13
environment:
- POSTGRES_USER=test
- POSTGRES_PASSWORD=test
- POSTGRES_DB=test
volumes:
- ./test/init:/docker-entrypoint-initdb.d
redis:
image: redis:6-alpine
# 单元测试服务
unit-test:
build:
context: .
dockerfile: Dockerfile.test
command: ["npm", "run", "test:unit"]
volumes:
- ./test-results:/app/test-results
# 集成测试服务
integration-test:
build:
context: .
dockerfile: Dockerfile.test
command: ["npm", "run", "test:integration"]
depends_on:
- app
- db
- redis
volumes:
- ./test-results:/app/test-results
# 性能测试服务
performance-test:
image: node:14
command: ["npm", "run", "test:performance"]
volumes:
- .:/app
working_dir: /app自动化测试流程
# 自动化测试脚本
#!/bin/bash
# run-tests.sh
echo "开始运行自动化测试..."
# 启动测试环境
docker-compose -f docker-compose.test.yml up -d
# 等待服务启动
echo "等待服务启动..."
sleep 30
# 运行单元测试
echo "运行单元测试..."
docker-compose -f docker-compose.test.yml run --rm unit-test
UNIT_TEST_EXIT_CODE=$?
# 运行集成测试
echo "运行集成测试..."
docker-compose -f docker-compose.test.yml run --rm integration-test
INTEGRATION_TEST_EXIT_CODE=$?
# 运行性能测试
echo "运行性能测试..."
docker-compose -f docker-compose.test.yml run --rm performance-test
PERFORMANCE_TEST_EXIT_CODE=$?
# 停止测试环境
docker-compose -f docker-compose.test.yml down -v
# 汇总测试结果
echo "=== 测试结果汇总 ==="
echo "单元测试: $([ $UNIT_TEST_EXIT_CODE -eq 0 ] && echo "通过" || echo "失败")"
echo "集成测试: $([ $INTEGRATION_TEST_EXIT_CODE -eq 0 ] && echo "通过" || echo "失败")"
echo "性能测试: $([ $PERFORMANCE_TEST_EXIT_CODE -eq 0 ] && echo "通过" || echo "失败")"
# 如果有任何测试失败,退出码为1
if [ $UNIT_TEST_EXIT_CODE -ne 0 ] || [ $INTEGRATION_TEST_EXIT_CODE -ne 0 ] || [ $PERFORMANCE_TEST_EXIT_CODE -ne 0 ]; then
echo "测试失败!"
exit 1
else
echo "所有测试通过!"
exit 0
fi部署阶段管理
镜像构建和推送
# 生产环境 Dockerfile
FROM node:14-alpine AS base
# 创建非 root 用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001 -G nodejs
# 安装生产依赖
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && \
npm cache clean --force
# 构建阶段
FROM base AS builder
COPY . .
RUN npm run build
# 生产阶段
FROM base AS production
COPY --from=builder --chown=nextjs:nodejs /app/dist ./dist
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
# 切换到非 root 用户
USER nextjs
# 配置健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
EXPOSE 3000
CMD ["node", "dist/index.js"]# 镜像构建和推送脚本
#!/bin/bash
# build-and-push.sh
# 镜像构建和推送脚本
IMAGE_NAME="myapp"
VERSION="${1:-latest}"
REGISTRY="registry.example.com"
echo "构建镜像: ${REGISTRY}/${IMAGE_NAME}:${VERSION}"
# 构建镜像
docker build -t ${REGISTRY}/${IMAGE_NAME}:${VERSION} .
# 推送镜像
docker push ${REGISTRY}/${IMAGE_NAME}:${VERSION}
# 同时推送 latest 标签(如果是版本标签)
if [ "$VERSION" != "latest" ]; then
docker tag ${REGISTRY}/${IMAGE_NAME}:${VERSION} ${REGISTRY}/${IMAGE_NAME}:latest
docker push ${REGISTRY}/${IMAGE_NAME}:latest
fi
echo "镜像推送完成: ${REGISTRY}/${IMAGE_NAME}:${VERSION}"环境部署配置
# docker-compose.prod.yml
version: '3.8'
services:
app:
image: registry.example.com/myapp:latest
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
order: start-first
rollback_config:
parallelism: 1
delay: 10s
failure_action: pause
order: stop-first
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
placement:
constraints:
- node.role == worker
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
- REDIS_URL=${REDIS_URL}
- LOG_LEVEL=info
secrets:
- db_password
- api_key
networks:
- frontend
- backend
depends_on:
- db
- redis
lb:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ssl_certs:/etc/nginx/ssl
networks:
- frontend
depends_on:
- app
db:
image: postgres:13
environment:
- POSTGRES_USER=prod
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
- POSTGRES_DB=myapp
volumes:
- db_data:/var/lib/postgresql/data
networks:
- backend
secrets:
- db_password
redis:
image: redis:6-alpine
networks:
- backend
networks:
frontend:
driver: overlay
backend:
driver: overlay
volumes:
db_data:
ssl_certs:
secrets:
db_password:
external: true
api_key:
external: true运维阶段管理
监控和告警
# docker-compose.monitoring.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus:v2.37.0
ports:
- "9090:9090"
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
grafana:
image: grafana/grafana-enterprise
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- prometheus
alertmanager:
image: prom/alertmanager:v0.24.0
ports:
- "9093:9093"
volumes:
- ./alertmanager/config.yml:/etc/alertmanager/config.yml
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.45.0
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
volumes:
prometheus_data:
grafana_data:# 监控脚本
#!/bin/bash
# monitor.sh
# 应用监控脚本
CONTAINERS=("app" "db" "redis")
ALERT_THRESHOLD_CPU=80
ALERT_THRESHOLD_MEM=80
for container in "${CONTAINERS[@]}"; do
# 获取资源使用情况
cpu_usage=$(docker stats --no-stream --format "{{.CPUPerc}}" $container | sed 's/%//')
mem_usage=$(docker stats --no-stream --format "{{.MemPerc}}" $container | sed 's/%//')
# 检查 CPU 使用率
if (( $(echo "$cpu_usage > $ALERT_THRESHOLD_CPU" | bc -l) )); then
echo "警告: 容器 $container CPU 使用率过高: ${cpu_usage}%"
# 发送告警
fi
# 检查内存使用率
if (( $(echo "$mem_usage > $ALERT_THRESHOLD_MEM" | bc -l) )); then
echo "警告: 容器 $container 内存使用率过高: ${mem_usage}%"
# 发送告警
fi
done日志管理
# docker-compose.logging.yml
version: '3.8'
services:
fluentd:
image: fluent/fluentd:v1.14-1
volumes:
- ./fluentd/conf:/fluentd/etc
- /var/lib/docker/containers:/var/lib/docker/containers
ports:
- "24224:24224"
- "24224:24224/udp"
elasticsearch:
image: elasticsearch:7.17.0
environment:
- discovery.type=single-node
ports:
- "9200:9200"
- "9300:9300"
volumes:
- es_data:/usr/share/elasticsearch/data
kibana:
image: kibana:7.17.0
ports:
- "5601:5601"
depends_on:
- elasticsearch
volumes:
es_data:# 日志清理脚本
#!/bin/bash
# log-cleanup.sh
# 日志清理脚本
MAX_LOG_SIZE="100m"
RETENTION_DAYS=7
# 清理 Docker 日志
echo "清理 Docker 日志..."
docker system prune -f
# 清理容器日志文件
for container in $(docker ps -q); do
log_file=$(docker inspect $container | grep LogPath | cut -d'"' -f4)
if [ -f "$log_file" ]; then
# 检查文件大小
file_size=$(du -m "$log_file" | cut -f1)
if [ "$file_size" -gt "${MAX_LOG_SIZE%?}" ]; then
echo "清理容器 $container 的日志文件: $log_file"
echo "" > "$log_file"
fi
fi
done
# 删除超过保留天数的日志
find /var/lib/docker/containers -name "*.log" -mtime +$RETENTION_DAYS -delete
echo "日志清理完成!"退役阶段管理
资源清理
# 应用退役脚本
#!/bin/bash
# app-retirement.sh
# 应用退役脚本
APP_NAME="myapp"
NAMESPACE="production"
echo "开始退役应用: $APP_NAME"
# 备份重要数据
echo "备份数据库..."
docker exec ${APP_NAME}-db pg_dump -U prod myapp > backup-$(date +%Y%m%d).sql
# 备份配置文件
echo "备份配置文件..."
docker cp ${APP_NAME}-app:/app/config ./config-backup-$(date +%Y%m%d)
# 停止应用服务
echo "停止应用服务..."
docker-compose -f docker-compose.prod.yml down
# 清理相关资源
echo "清理相关资源..."
docker volume rm ${APP_NAME}_db_data
docker network rm ${APP_NAME}_frontend ${APP_NAME}_backend
# 删除镜像
echo "删除应用镜像..."
docker rmi registry.example.com/${APP_NAME}:latest
# 清理监控和日志配置
echo "清理监控和日志配置..."
# 删除相关的监控配置文件
# 删除相关的日志配置
echo "应用退役完成!"数据迁移
# 数据迁移脚本
#!/bin/bash
# data-migration.sh
# 数据迁移脚本
SOURCE_DB="postgresql://prod:password@old-db:5432/myapp"
TARGET_DB="postgresql://prod:password@new-db:5432/myapp"
echo "开始数据迁移..."
# 备份源数据库
echo "备份源数据库..."
pg_dump $SOURCE_DB > source-backup-$(date +%Y%m%d).sql
# 恢复到目标数据库
echo "恢复到目标数据库..."
psql $TARGET_DB < source-backup-$(date +%Y%m%d).sql
# 验证数据完整性
echo "验证数据完整性..."
source_count=$(psql $SOURCE_DB -t -c "SELECT COUNT(*) FROM users;")
target_count=$(psql $TARGET_DB -t -c "SELECT COUNT(*) FROM users;")
if [ "$source_count" -eq "$target_count" ]; then
echo "数据迁移成功!记录数: $source_count"
else
echo "数据迁移失败!源记录数: $source_count, 目标记录数: $target_count"
exit 1
fi
echo "数据迁移完成!"生命周期管理最佳实践
自动化流水线
# .gitlab-ci.yml
stages:
- build
- test
- deploy
- monitor
variables:
IMAGE_NAME: "registry.example.com/myapp"
VERSION: "${CI_COMMIT_SHA}"
build:
stage: build
script:
- docker build -t $IMAGE_NAME:$VERSION .
- docker push $IMAGE_NAME:$VERSION
- docker tag $IMAGE_NAME:$VERSION $IMAGE_NAME:latest
- docker push $IMAGE_NAME:latest
only:
- main
test:
stage: test
script:
- docker-compose -f docker-compose.test.yml up -d
- sleep 30
- docker-compose -f docker-compose.test.yml run --rm unit-test
- docker-compose -f docker-compose.test.yml run --rm integration-test
- docker-compose -f docker-compose.test.yml down -v
only:
- main
deploy_staging:
stage: deploy
script:
- docker stack deploy -c docker-compose.staging.yml myapp-staging
only:
- develop
deploy_production:
stage: deploy
script:
- docker stack deploy -c docker-compose.prod.yml myapp-prod
when: manual
only:
- main
monitor:
stage: monitor
script:
- ./scripts/monitor.sh
only:
- main配置管理
# 配置管理脚本
#!/bin/bash
# config-management.sh
# 配置管理脚本
ENVIRONMENT="${1:-development}"
CONFIG_DIR="./config/$ENVIRONMENT"
echo "应用 $ENVIRONMENT 环境配置..."
# 验证配置文件
if [ ! -d "$CONFIG_DIR" ]; then
echo "错误: 配置目录不存在: $CONFIG_DIR"
exit 1
fi
# 应用配置
docker config create myapp-config-$ENVIRONMENT $CONFIG_DIR/app.conf
docker config create myapp-db-config-$ENVIRONMENT $CONFIG_DIR/db.conf
# 更新服务配置
docker service update \
--config-rm myapp-config \
--config-add source=myapp-config-$ENVIRONMENT,target=/app/config/app.conf \
myapp
echo "配置应用完成!"版本管理
# 版本管理脚本
#!/bin/bash
# version-management.sh
# 版本管理脚本
VERSION_FILE="VERSION"
CURRENT_VERSION=$(cat $VERSION_FILE)
echo "当前版本: $CURRENT_VERSION"
# 获取版本变更类型
echo "选择版本变更类型:"
echo "1) 补丁版本 (0.0.1)"
echo "2) 次要版本 (0.1.0)"
echo "3) 主要版本 (1.0.0)"
read -p "请输入选择 (1-3): " choice
# 计算新版本
case $choice in
1)
NEW_VERSION=$(echo $CURRENT_VERSION | awk -F. '{$NF = $NF + 1;} 1' | sed 's/ /./g')
;;
2)
NEW_VERSION=$(echo $CURRENT_VERSION | awk -F. '{$(NF-1) = $(NF-1) + 1; $NF = 0;} 1' | sed 's/ /./g')
;;
3)
NEW_VERSION=$(echo $CURRENT_VERSION | awk -F. '{$1 = $1 + 1; $(NF-1) = 0; $NF = 0;} 1' | sed 's/ /./g')
;;
*)
echo "无效选择"
exit 1
;;
esac
# 更新版本文件
echo $NEW_VERSION > $VERSION_FILE
# 创建 Git 标签
git add $VERSION_FILE
git commit -m "Bump version to $NEW_VERSION"
git tag -a "v$NEW_VERSION" -m "Release version $NEW_VERSION"
echo "版本已更新到: $NEW_VERSION"通过本节内容,我们深入了解了容器化应用的生命周期管理,包括开发、测试、部署、运维和退役各个阶段的管理策略和实践方法。掌握这些技能将帮助您在生产环境中更好地管理容器化应用的完整生命周期。
