Bitbucket+DockerHub+AWS部署:Java Gradle项目如何规避制品过期?
Docker制品过期问题解析与解决方案
项目背景
我维护一个Java+Gradle项目,通过Bitbucket Pipelines的bitbucket-pipelines.yml完成构建与部署,核心配置分为两个步骤:
步骤1:构建应用并推送Docker镜像
- step: name: Build deployable & Image Scan services: - docker caches: - gradle - docker image: name: comp/gradle:7.3.0-jdk17 username: "$DOCKERHUB_READONLY_USER" password: "$DOCKERHUB_READONLY_PASSWORD" email: "$DOCKERHUB_READONLY_EMAIL" size: 2x script: # environment - source set_env.sh # account - . ./auth.sh $AWS_ACCOUNT_ID_DEV DEV # build - gradle build -x test - docker build -t my-service:latest comp-my-service-app # Vulnerability Scanning - > twistlock_scan.sh \ "my-service:latest" \ "$TWISTLOCK_CLIENT_ID" \ "$TWISTLOCK_API_KEY" \ "$TWISTLOCK_ENDPOINT" \ "$BITBUCKET_REPO_SLUG\my-service:$VERSION" || true # tag - docker tag my-service:latest ${AWS_ACCOUNT_ID_DEV}some.where.us-east-2.amazonaws.com/my-service:$VERSION # push - docker push ${AWS_ACCOUNT_ID_DEV}some.where.us-east-2.amazonaws.com/my-service:$VERSION
步骤2:拉取镜像并触发AWS ECS部署
- step: name: Dev deployment: Development services: - docker script: # environment - source set_env.sh # account - . ./auth.sh $AWS_ACCOUNT_ID_DEV DEV # pull - docker pull ${AWS_ACCOUNT_ID_DEV}some.where.us-east-2.amazonaws.com/my-service:$VERSION # tag - docker tag ${AWS_ACCOUNT_ID_DEV}some.where.us-east-2.amazonaws.com/my-service:$VERSION ${AWS_ACCOUNT_ID_DEV}some.where.us-east-2.amazonaws.com/my-service:latest # push - docker push ${AWS_ACCOUNT_ID_DEV}some.where.us-east-2.amazonaws.com/my-service:latest # deploy - aws ecs update-service --cluster my-service --service my-service --region us-east-2 --force-new-deployment # wait until stable - ecs_deploy_check.py --cluster_name my-service --service_name my-service --region us-east-2 --timeout 600
问题解答
1. 制品过期实际是如何发生的?
结合你使用AWS ECR作为镜像仓库的场景,制品(Docker镜像)过期主要有以下几种情况:
- 仓库生命周期规则自动清理:如果ECR仓库配置了生命周期策略(比如保留最近N个镜像、删除超过X天的镜像),符合条件的旧镜像会被自动删除,导致无法拉取。
- 标签被覆盖导致旧版本丢失:你的流程中存在将
$VERSION标签镜像重新打为latest并推送的操作,若后续有新构建覆盖latest标签,旧的latest对应的镜像层如果没有其他标签关联,可能会被仓库的垃圾回收机制清理。 - 镜像无有效标签关联:如果某个镜像只有一个标签,且该标签被新镜像覆盖,旧镜像会变成"无标签镜像",这类镜像通常会被仓库的自动清理规则优先处理。
- 权限变更:若AWS IAM权限调整,导致拉取镜像的账号失去对应仓库的读取权限,也会出现类似"过期"的无法拉取情况,但这属于权限问题而非真正的制品过期。
2. 如何避免制品过期或控制过期周期?
针对你的现有流程,可通过以下方式优化:
- 配置ECR生命周期规则:在AWS控制台为ECR仓库设置明确的生命周期策略,比如:
- 保留最近30个带版本标签的镜像
- 保留
latest标签的镜像不被自动清理 - 仅删除超过90天的无标签镜像
- 避免标签覆盖,使用唯一标识:将镜像标签设置为唯一值,比如结合Git提交哈希(
$BITBUCKET_COMMIT)和版本号,生成类似$VERSION-$BITBUCKET_COMMIT的标签,确保每个构建的镜像都有唯一标签,不会被后续构建覆盖。 - 为重要镜像打多标签:对于需要长期保留的镜像(比如正式发布版本),除了版本标签外,额外添加
stable或release-$VERSION等固定标签,避免因标签覆盖导致镜像被清理。 - 在Pipeline中添加镜像可用性验证:在部署步骤拉取镜像后,添加
docker inspect命令验证镜像是否有效,避免因镜像已被清理导致部署失败。 - 定期清理无用镜像:主动清理测试环境的旧镜像,比如在Pipeline中添加步骤,删除超过7天的测试版本镜像,既节省存储成本,又避免无意义的镜像堆积。
- 固定构建依赖的镜像版本:你的构建使用
comp/gradle:7.3.0-jdk17镜像,确保该镜像不会被上游仓库删除,可考虑将其同步到自己的ECR仓库,避免依赖外部镜像过期。
内容的提问来源于stack exchange,提问作者Ivan Karotki
相关产品推荐
相关产品推荐

