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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:34:59