You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在AWS CodeDeploy中用docker-compose部署最新代码且避免停机

问题描述

我通过AWS CodeDeploy结合docker-compose部署了一个Next.js应用,搭建了预发布环境:开发者向staging分支推送新提交时,会自动触发CodeDeploy创建新部署。
应用的appspec.yml配置了启动脚本,执行docker-compose build和docker-compose up命令。我原本以为构建时加--no-cache就能基于最新代码启动容器,但部署成功后,应用并未体现代码变更。
请问如何确保每次部署都基于最新代码创建容器,同时避免服务停机?

当前配置文件

appspec.yml

version: 0.0
os: linux
files:
  - source: .
    destination: /home/ec2-user/app/
hooks:
  ApplicationStart:
   - location: scripts/run.sh
     timeout: 300
     runas: root

run.sh

#!/bin/bash
cd /home/ec2-user/app
docker-compose build --no-cache
docker-compose up -d
解决办法

1. 确认代码同步是否到位

CodeDeploy的文件复制环节可能出现缓存或遗漏,先验证目标服务器的代码是否为最新版本:

  • 登录EC2实例,进入/home/ec2-user/app目录,执行git log查看提交记录,和staging分支的最新提交ID对比
  • 如果代码未更新,检查CodeDeploy部署日志,确认文件复制阶段是否报错,或者是否配置了ignore_files规则排除了关键代码文件

2. 优化Docker构建逻辑,强制更新所有层级

即便加了--no-cache,Dockerfile的分层设计也可能导致旧层被复用,可做以下调整:

  • 构建时添加--pull参数,拉取基础镜像的最新版本:docker-compose build --no-cache --pull
  • 检查Dockerfile,确保先复制package.json/package-lock.json安装依赖,再复制其余代码;如果依赖有更新,确保构建过程中重新执行了npm install
  • 确认Next.js的静态构建产物(/.next目录)在构建时正确复制到容器内,且构建命令npm run build已执行

3. 实现滚动更新,避免服务停机

当前docker-compose up -d会直接重启容器,可能导致短暂停机。可以通过以下方式实现零停机部署:

  • 在docker-compose.yml中为服务配置deploy.replicas: 2(需启用Docker Swarm模式,或使用docker-compose up --scale动态调整副本数)
  • 修改启动脚本,先启动新容器,等健康检查通过后再停止旧容器:
    #!/bin/bash
    cd /home/ec2-user/app
    
    # 给新镜像打唯一标签(用时间戳确保唯一性)
    TAG=$(date +%Y%m%d%H%M%S)
    docker-compose build --no-cache --pull
    docker tag your-app-image:latest your-app-image:$TAG
    
    # 启动新容器,临时扩容副本数
    docker-compose up -d --scale your-app-service=2
    
    # 等待新容器完成启动和健康检查
    sleep 30
    
    # 定位并停止旧容器
    OLD_CONTAINER_ID=$(docker ps -q -f "name=your-app-service" -f "label=com.docker.compose.image=your-app-image:latest" | head -n 1)
    if [ ! -z "$OLD_CONTAINER_ID" ]; then
        docker stop $OLD_CONTAINER_ID
        docker rm $OLD_CONTAINER_ID
    fi
    
    # 可选:将副本数调回1
    docker-compose up -d --scale your-app-service=1
    

4. 清理旧资源,避免误启动旧镜像

部署后清理未使用的容器和镜像,防止磁盘占用过高,同时避免意外启动旧版本:

# 清理已退出的容器
docker container prune -f
# 清理未被使用的镜像
docker image prune -a -f

5. 完善CodeDeploy生命周期钩子

添加BeforeInstall钩子,在部署前清理目标目录的旧代码,避免残留文件干扰:
修改appspec.yml:

hooks:
  BeforeInstall:
    - location: scripts/cleanup.sh
      timeout: 60
      runas: root
  ApplicationStart:
    - location: scripts/run.sh
      timeout: 300
      runas: root

cleanup.sh内容:

#!/bin/bash
rm -rf /home/ec2-user/app/*

内容的提问来源于stack exchange,提问作者everspader

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 02:15:43