Search code examples
dockerfilegoogle-cloud-buildcloudbuild.yaml

Using 2 Dockerfiles in Cloud Build to re-use intermediary step image if CloudBuild fails


Cloud Build fails with Timeout Error (I'm trying to deploy CloudRun with Prophet). Therefore I'm trying to split the Dockerfile into two (saving the image in between in case it fails). I'd split the Dockerfile like this:

  • Dockerfile_one: python + prophet's dependencies
  • Dockerfile_two: image_from_Dockerfile_one + prophet + other dependencies

What should cloudbuild.yaml should look like to:

  1. if there is a previously image available skip the step, else run the step with the Dockerfile_one and save the image
  2. use the image from the step (1), add more dependencies to it and save the image for deploy

Here is how cloudbuild.yaml looks like right now

steps:
#  create gcr source directory
- name: 'bash'
  args:
    - '-c'
    - |
      echo 'Creating gcr_source directory for ${_GCR_NAME}'
      mkdir _gcr_source
      cp -r cloudruns/${_GCR_NAME}/. _gcr_source

# Build the container image
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/${_GCR_NAME}', '.']
  dir: '_gcr_source'

# Push the container image to Container Registry
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'gcr.io/$PROJECT_ID/${_GCR_NAME}']

# Deploy container image to Cloud Run
- name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: gcloud
  args:
  - run
  - deploy
  - ${_GCR_NAME}
  - --image=gcr.io/$PROJECT_ID/${_GCR_NAME}

Thanks a lot!


Solution

  • You need to have 2 pipelines

    1. The first one create the base image. Like that, you can trigger it everytime that you need to rebuild this base image, with, possibly a different lifecycle than your application lifecycle. Something similar to that
    steps:
    - name: 'gcr.io/cloud-builders/docker'
      args: ['build', '-t', 'gcr.io/<PROJECT_ID>/base-image', '-f', 'DOCKERFILE_ONE', '.']
    images: ['gcr.io/<PROJECT_ID>/base-image']
    
    1. Then, in your second dockerfile, start from the base image and use a second Cloud Build pipeline to build, push and deploy it (as you do in your 3 last steps in your question)
    FROM gcr.io/<PROJECT_ID>/base-image
    COPY .....
    ....
    ...