CircleCI has been adding some baked in support for Google Cloud, negating much of this blog post.
Please check out the links below:
CircleCI is a great build tool with a lot of flexibility. They even have a good tutorial on interacting with docker with a special section referencing Google Compute Engine and Kubernetes. The only slight difference here is that I want to deploy directly to Google's Container Registry (GCR) rather than deploy my own registry, which is slightly more involved. So, let's get started.
Our starting point is circleci/docker-hello-google, then a little help from this fork bellkev/docker-hello-google. These repos handle a lot of the other aspects of building a docker image, running, and testing it.
From the command line, it is really easy to push docker images to the GCR.
docker tag user/example-image gcr.io/your-project-id/example-image gcloud docker push gcr.io/your-project-id/example-image
However, in a build environment, we can't just use
gcloud auth login with our Google credentials. We need to first set up a service account. You will need the email address and downloaded json file
Once you've created your service account, set up the following environment variables in CircleCI:
|GCLOUD_KEY||base64-encoded version of
On OSX and Linux, you can get the base64 encoded version like this:
cat project_name-xxxxx.json | base64
Now we can write a script that authenticates us with
gcloud and name it
#! /bin/bash echo $GCLOUD_KEY | base64 --decode > gcloud.p12 gcloud auth activate-service-account $GCLOUD_EMAIL --key-file gcloud.p12 ssh-keygen -f ~/.ssh/google_compute_engine -N ""
Now we just need to set up the
circle.yml with the following sections:
CLOUDSDK_* environment variables help with non-interactive use of the
machine: environment: CLOUDSDK_CORE_DISABLE_PROMPTS: 1 CLOUDSDK_PYTHON_SITEPACKAGES: 1 CLOUDSDK_COMPUTE_ZONE: us-central1-b CLOUDSDK_CORE_PROJECT: $GCLOUD_PROJECTID PATH: $PATH:/home/ubuntu/google-cloud-sdk/bin python: version: 2.7.3 services: - docker
Check out script/ensure-gcloud-installed.sh here. We build the docer image using our
$EXTERNAL_REGISTRY_ENDPOINT and the
$CIRCLE_SHA1 and use the standard CircleCI method of caching docker layers.
dependencies: cache_directories: - ~/google-cloud-sdk - ~/docker override: - script/ensure-gcloud-installed.sh - if [[ -e ~/docker/image.tar ]]; then docker load -i ~/docker/image.tar; fi - docker build -t $EXTERNAL_REGISTRY_ENDPOINT/hello:$CIRCLE_SHA1 . - mkdir -p ~/docker; docker save $EXTERNAL_REGISTRY_ENDPOINT/hello:$CIRCLE_SHA1 > ~/docker/image.tar
Next, we use our script from above to authenticate with gcloud, then use the
gcloud docker push almost like normal. I had to add
> /dev/null to ignore the output as it was causing the following error: FATA HTTP code 500 while uploading metadata: "invalid character 'I' looking for beginning of value"
deployment: prod: branch: master commands: - script/auth-gcloud.sh - gcloud docker push $EXTERNAL_REGISTRY_ENDPOINT/hello > /dev/null
The working code for this example can be found at my fork. I imagine these same principles can be applied to push docker images to Google Cloud Registry from other build tools like Jenkins or TravisCI.