Building Docker images with GitHub Actions and Google Cloud
Building Docker images with Google Cloud Build and pushing them to Google Cloud Registry using GitHub Actions as part of your CI pipeline.
Also available in German at miragon.io.
In the last parts of our GitHub Actions blog series, we took a closer look at Gradle builds. But deploying to the cloud usually involves using pre-built Docker images, not JAR files. How can we build these as part of our CI pipeline?
For this purpose, we have developed the GitHub action docker-cloud-build
and made it available open source in our GitHub repository. Using this action, a finished Docker image can be built in just one step as a result of a Dockerfile and a list of input files, and is then available in Google Cloud Registry.
Furthermore, the build output can be displayed in the GitHub UI to see at a glance which tags were created and if the build was successful.
Getting Started
To use the action, we first need to add a new step to our action.yaml file. It will look like this, for example:
- name: Build Docker Image
uses: FlowSquad/docker-cloud-build@v1.0.1
with:
gcp-project-id: my-project-id
gcp-service-account-key: ${{ secrets.GCP_SA_KEY }}
image-name: my-image-name
image-sources: build/libs/*.jar,Dockerfile,some-other-file
github-token: ${{ secrets.GITHUB_TOKEN }}
The configuration above is the minimal possible configuration. The available parameters can be used to extensively customize the behavior of the action. The parameter gcp-project-id
contains the ID of the project in Google Cloud that is supposed to be used. The default region for Google Cloud Registry is eu.gcr.io
. This can be customized with the gcp-gcr-region
parameter.
You can specify the name of the image under image-name
. The tag is then created dynamically. The files required for the build are specified as image-sources
. All files and folders from the GitHub actions workspace can be specified. Wildcards such as *
or ?
are also supported. The files then need to be copied into the finished image within the Dockerfile.
Authentication
Under gcp-service-account-token
a base64 encoded service account JSON file must be specified. This will be used for authenticating with GCP. The service account requires the following permissions:
cloudbuild.builds.create # Required to start cloud builds
cloudbuild.builds.get # Required to check build status
storage.objects.create # Required to upload build input data
storage.objects.get # ^ same
storage.objects.list # ^ same
storage.objects.delete # Required to clean up after build
The required JSON file can be created in Google Cloud IAM under Service Accounts. To do this, select the desired service account, switch to the Keys tab, and create a new key of type JSON.
GitHub Integration
The github-token
is only required if the github-disabled
parameter is not set to true
. Typically, the default token provided by GitHub Actions is sufficient for this. It is necessary to set the commit status and/or the release notes. More on this later.
Before we can run the action, we first need to create a bucket in Google Cloud Storage to cache the input files for the build. By default, a bucket named ${projectId}_cloudbuild
is used for this purpose. The name can be overridden with the gcp-cloud-storage-bucket
parameter.
If you run the action now, the corresponding image will be built and tagged as $branch-$commitSha-$yyyy.$mm.$dd-$hh.$mm.$ss
by default. The first part is the (normalized) branch name, the second part is the 7-character short hash of the commit used, and the third part is the date and time of the build.
If the action is triggered by a new tag being created in GitHub, the tag name is also set as an image tag. The available parameters can be used to customize the tags used. For example, the default
tag can always be set globally or for the corresponding branch, or the format of the default tag can be changed. Custom tags are also possible.
If desired, the built image tags can then be displayed as commit status in GitHub. This makes it clear at a glance with which name the image can be retrieved. The format of the message can also be customized.
If the action is triggered by a newly created release, the built tags can also be added to the corresponding release notes. This can make it easier for users of the image to find the relevant links. Whether only the default tag or all tags should be included in the release notes can be customized.
All available parameters and more information can be found here. We use this action across the board in our build pipelines to build Docker images for frontend, backend, and other applications that are then used in our Kubernetes clusters. To deploy them, we use the GitOps approach. More on this in a future blog post!