如何在 Google 云构建中构建 Docker 图像并在以后的构建步骤中使用?
How can I build a Docker Image in Google Cloud Build and use in later Build Steps?
在我的 Rails 项目中,我在存储库中有一个 Docker 图像,用于数据库迁移和单元测试。在 运行 migrations/testing 之前,我可能需要更新图像上的宝石。但是,似乎即使在更新 Gems 之后,更新后的图像(未推送到存储库,但在 migration/testing 之前的构建步骤中)也不可用于未来的构建步骤。
我的 cloudbuild.yaml 看起来像这样:
steps:
- id: update_gems
name: 'gcr.io/cloud-builders/docker'
args: [ 'build', '-t', "us-central1-docker.pkg.dev/$PROJECT_ID/myregistry/myimage:deploy",
'--build-arg', 'PROJECT=${PROJECT_ID}', '-f', 'docker/bundled.Dockerfile', '.' ]
- id: db_migration
name: "gcr.io/google-appengine/exec-wrapper"
args: ["-i", "us-central1-docker.pkg.dev/$PROJECT_ID/myregistry/myimage:deploy",
"-e", "RAILS_ENV=${_RAILS_ENV}",
"-e", "INSTANCE_CONNECTION_NAME=${_INSTANCE_CONNECTION_NAME}",
"-s", "${_INSTANCE_CONNECTION_NAME}",
"--", "./bin/rake", "db:migrate"]
- id: unit_test
name: "gcr.io/google-appengine/exec-wrapper"
args: ["-i", "us-central1-docker.pkg.dev/$PROJECT_ID/myregistry/myimage:deploy",
"-e", "RAILS_ENV=test",
"-e", "INSTANCE_CONNECTION_NAME=${_INSTANCE_CONNECTION_NAME}",
"-s", "${_INSTANCE_CONNECTION_NAME}",
"--", "./bin/rspec"]
- id: deploy_to_GAE
name: gcr.io/cloud-builders/gcloud
args: ['app', 'deploy', '--project', '${PROJECT_ID}', 'app.yaml']
第一步中引用的 Docker 文件如下所示:
ARG PROJECT
FROM us-central1-docker.pkg.dev/${PROJECT}/myregistry/myimage:deploy
WORKDIR /workspace
ADD Gemfile* ./
RUN bundle update
RUN bundle install
在触发的 Cloud Build 期间,我看到它更新了 Gems 并创建了一个新的散列,如下所示:
然后在 db_migration
步骤中,我看到它在更新 Gems 之前拉取旧图像:
这可以在 update_gems
步骤日志中验证,其中更新前的图像哈希匹配(即新提取的图像哈希,但尚未更新其 Gems):
我意识到一个解决方法是在构建更新后的图像后推送它,这确实有效。例如,我可以在 update_gems
步骤之后添加此步骤:
- id: update_image
name: 'gcr.io/cloud-builders/docker'
args: [ 'push', 'us-central1-docker.pkg.dev/$PROJECT_ID/myregistry/myimage:deploy' ]
然而,这引出了一个问题,为什么新的 udate_image
构建步骤可以访问由 update_gems
步骤构建的映像,而其他后续步骤则不能。
图像存储在本地,在本地 docker 注册表中,Docker 可以访问。这就是为什么你可以用 Docker.
来推送它
但是,当您使用另一个步骤时,例如 gcr.io/google-appengine/exec-wrapper
,Docker 不再加载到运行时上下文中,因此本地 docker 注册表是 unknown/not活跃。
所以,解决方案是:
- 要么将镜像推送到外部,然后再使用。像这样,使用的不是本地registry而是外部registry,任何步骤都有效。
- 或在您当前的运行时步骤映像上安装 docker(或使用 Docker 作为步骤映像并在该映像上安装您需要的东西)-> 这会很困难,我不推荐这样。
在我的 Rails 项目中,我在存储库中有一个 Docker 图像,用于数据库迁移和单元测试。在 运行 migrations/testing 之前,我可能需要更新图像上的宝石。但是,似乎即使在更新 Gems 之后,更新后的图像(未推送到存储库,但在 migration/testing 之前的构建步骤中)也不可用于未来的构建步骤。
我的 cloudbuild.yaml 看起来像这样:
steps:
- id: update_gems
name: 'gcr.io/cloud-builders/docker'
args: [ 'build', '-t', "us-central1-docker.pkg.dev/$PROJECT_ID/myregistry/myimage:deploy",
'--build-arg', 'PROJECT=${PROJECT_ID}', '-f', 'docker/bundled.Dockerfile', '.' ]
- id: db_migration
name: "gcr.io/google-appengine/exec-wrapper"
args: ["-i", "us-central1-docker.pkg.dev/$PROJECT_ID/myregistry/myimage:deploy",
"-e", "RAILS_ENV=${_RAILS_ENV}",
"-e", "INSTANCE_CONNECTION_NAME=${_INSTANCE_CONNECTION_NAME}",
"-s", "${_INSTANCE_CONNECTION_NAME}",
"--", "./bin/rake", "db:migrate"]
- id: unit_test
name: "gcr.io/google-appengine/exec-wrapper"
args: ["-i", "us-central1-docker.pkg.dev/$PROJECT_ID/myregistry/myimage:deploy",
"-e", "RAILS_ENV=test",
"-e", "INSTANCE_CONNECTION_NAME=${_INSTANCE_CONNECTION_NAME}",
"-s", "${_INSTANCE_CONNECTION_NAME}",
"--", "./bin/rspec"]
- id: deploy_to_GAE
name: gcr.io/cloud-builders/gcloud
args: ['app', 'deploy', '--project', '${PROJECT_ID}', 'app.yaml']
第一步中引用的 Docker 文件如下所示:
ARG PROJECT
FROM us-central1-docker.pkg.dev/${PROJECT}/myregistry/myimage:deploy
WORKDIR /workspace
ADD Gemfile* ./
RUN bundle update
RUN bundle install
在触发的 Cloud Build 期间,我看到它更新了 Gems 并创建了一个新的散列,如下所示:
然后在 db_migration
步骤中,我看到它在更新 Gems 之前拉取旧图像:
这可以在 update_gems
步骤日志中验证,其中更新前的图像哈希匹配(即新提取的图像哈希,但尚未更新其 Gems):
我意识到一个解决方法是在构建更新后的图像后推送它,这确实有效。例如,我可以在 update_gems
步骤之后添加此步骤:
- id: update_image
name: 'gcr.io/cloud-builders/docker'
args: [ 'push', 'us-central1-docker.pkg.dev/$PROJECT_ID/myregistry/myimage:deploy' ]
然而,这引出了一个问题,为什么新的 udate_image
构建步骤可以访问由 update_gems
步骤构建的映像,而其他后续步骤则不能。
图像存储在本地,在本地 docker 注册表中,Docker 可以访问。这就是为什么你可以用 Docker.
来推送它但是,当您使用另一个步骤时,例如 gcr.io/google-appengine/exec-wrapper
,Docker 不再加载到运行时上下文中,因此本地 docker 注册表是 unknown/not活跃。
所以,解决方案是:
- 要么将镜像推送到外部,然后再使用。像这样,使用的不是本地registry而是外部registry,任何步骤都有效。
- 或在您当前的运行时步骤映像上安装 docker(或使用 Docker 作为步骤映像并在该映像上安装您需要的东西)-> 这会很困难,我不推荐这样。