Custom Build Steps

When writing your build requests, you can use the supported, open-source build steps provided by Container Builder, or you define your own custom build steps.

A custom build step is a container image that the Container Builder worker VM pulls and runs with your source volume-mounted to /workspace. Your custom build step can execute any script or binary inside the container; as such, it can do anything a container can do.

Custom build steps are useful for:

  • Downloading source code or packages from external locations
  • Using an external tool chain
  • Caching any necessary libraries
  • Pre-building source (with Container Builder responsible only for potentially packaging the build into a container image)

A custom build step runs with the source mounted under /workspace, and is run with a working directory somewhere in /workspace. Any files left in /workspace by a given build step are available to other build steps, whether those steps are run concurrently or subsequently.

Your custom build step can push to or pull from Google Container Registry repository (hosted at gcr.io/$PROJECT-NAME/) to which your builder service account has access. The docker command-line tool credentials are not sufficient to provide authenticated access to Docker Hub.

Creating a custom build step

To create a custom build step, you can create a build request file that builds and pushes the build step image to an image registry, such as Container Registry, that the builder service account can access. Alternatively, you can use another tool to build the custom build step image, then store it in an image registry. Once this is complete, you can invoke your custom build step in future builds.

The Creating a Custom Build Step tutorial walks you through creating an example custom build step. See also Anatomy of a build step.

About the entrypoint field

Your image's Dockerfile may have an ENTRYPOINT and/or CMD field. ENTRYPOINT specifies the entry point to use for your custom build step if the container is to be run as an executable. CMD provides defaults for execution and, if ENTRYPOINT is omitted, should include an executable.

In a build request, the optional entrypoint field defines how the build step should be run when it is invoked. For example, you can specify the main command that should be called when the build step is run: the docker build step's entry point is "/usr/bin/docker". When you use your build step in a later build, you can override the Dockerfile ENTRYPOINT by specifying an entrypoint in that build.

If you do not specify the entrypoint field in your build step's build request file and the build step's image did not have an ENTRYPOINT specified in its Dockerfile, the first item in args is used as the entry point with the remaining items in args as the arguments.

Example build requests for custom build steps

In the example below, Container Builder builds and pushes a container image called gcr.io/$PROJECT_ID/gcloud, then invokes the image to ensure that it functions properly as a build step.

# In this directory, run the following command to build this builder.
# $ gcloud container builds submit . --config=cloudbuild.yaml

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '--tag=gcr.io/$PROJECT_ID/gcloud', '.']

# Simple unit test: invoke the new gcloud container to confirm that it was
# built correctly.
- name: 'gcr.io/$PROJECT_ID/gcloud'
  args: ['info']

# Invoke a command that requires auth, to check that it gets piped through
# correctly.
- name: 'gcr.io/$PROJECT_ID/gcloud'
  args: ['source', 'repos', 'clone', 'default']

images: ['gcr.io/$PROJECT_ID/gcloud']

The following example is the build request for the supported docker build step. This build request includes several comments that explain the build.

# In this directory, run the following command to build this builder.
# $ gcloud container builds submit . --config=cloudbuild.yaml

steps:
# Build all supported versions.
- name: 'gcr.io/cloud-builders/docker'
  args:
  - 'build'
  - '--build-arg=DOCKER_VERSION=1.12.6-0~ubuntu-trusty'
  - '--tag=gcr.io/$PROJECT_ID/docker:1.12.6'
  - '.'
  id: '1.12.6'
- name: 'gcr.io/cloud-builders/docker'
  args:
  - 'build'
  - '--build-arg=DOCKER_VERSION=17.05.0~ce-0~ubuntu-trusty'
  - '--tag=gcr.io/$PROJECT_ID/docker:17.05'
  - '.'
  id: '17.05'
- name: 'gcr.io/cloud-builders/docker'
  args:
  - 'build'
  - '--build-arg=DOCKER_VERSION=17.06.1~ce-0~ubuntu'
  - '--tag=gcr.io/$PROJECT_ID/docker:17.06.1'
  - '--file=Dockerfile-17.06.1'
  - '.'
  id: '17.06.1'
# Future supported versions of docker builder go here.

# Test each version by using it to run "docker build" on itself.
- name: 'gcr.io/$PROJECT_ID/docker:1.12.6'
  args:
  - 'build'
  - '--build-arg=DOCKER_VERSION=1.12.6-0~ubuntu-trusty'
  - '.'
  wait_for: ['1.12.6']
- name: 'gcr.io/$PROJECT_ID/docker:17.05'
  args:
  - 'build'
  - '--build-arg=DOCKER_VERSION=17.05.0~ce-0~ubuntu-trusty'
  - '.'
  wait_for: ['17.05']
- name: 'gcr.io/$PROJECT_ID/docker:17.06.1'
  args:
  - 'build'
  - '--build-arg=DOCKER_VERSION=17.06.1~ce-0~ubuntu'
  - '--file=Dockerfile-17.06.1'
  - '.'
  wait_for: ['17.06.1']
# Tests for future supported versions of docker builder go here.

# Tag the latest version as :latest. We use gcr.io/cloud-builders/docker here
# and not gcr.io/$PROJECT_ID/docker because the latter may not yet exist.
- name: 'gcr.io/cloud-builders/docker'
  args: ['tag', 'gcr.io/$PROJECT_ID/docker:17.06.1', 'gcr.io/$PROJECT_ID/docker']
  wait_for: ['17.06.1']
  id: 'latest'

# Here are some things that can be done with this builder:

# Do the same build, but give the image a different name. Note that
# "docker-again" is absent from the "images" list below, so this image is built
# but is not pushed to the repository.
- name: 'gcr.io/$PROJECT_ID/docker'
  args:
  - 'build'
  - '--build-arg=DOCKER_VERSION=1.12.6-0~ubuntu-trusty'
  - '--tag=gcr.io/$PROJECT_ID/docker-again'
  - '.'
  wait_for: ['latest']

# Get info about an image. This effectively runs the "docker inspect" command on
# the image built above.
- name: 'gcr.io/$PROJECT_ID/docker'
  args: ['inspect', 'gcr.io/$PROJECT_ID/docker']
  wait_for: ['latest']
# Execute a container. The "busybox" container is executed within the docker
# build step to echo "Hello, world!"
- name: 'gcr.io/$PROJECT_ID/docker'
  args: ['run', 'busybox', 'echo', 'Hello, world!']
  wait_for: ['latest']

images:
- 'gcr.io/$PROJECT_ID/docker:latest'
- 'gcr.io/$PROJECT_ID/docker:1.12.6'
- 'gcr.io/$PROJECT_ID/docker:17.05'
- 'gcr.io/$PROJECT_ID/docker:17.06.1'

Example open-source custom build steps

Below are additional examples of open-source custom build steps provided by Container Builder:

  • gcr.io/cloud-builders/maven is an image with Apache Maven installed. Its entrypoint is the mvn command-line tool.

  • gcr.io/cloud-builders/go is an image with the go command-line tool and a wrapper script installed. Before invoking go, the wrapper script sets up the Go build configuration by inspecting the environment (as specified in the env field) and the build source.

Monitor your resources on the go

Get the Google Cloud Console app to help you manage your projects.

Send feedback about...

Cloud Container Builder Documentation