Publishing Google Cloud Container Registry Images from Gitlab CI

Grant Forrest

Since I had some trouble getting this to work, I thought I’d write up a post about it to see if I can help anyone else.

At the present time (May 21, 2018), this is the best I’ve come up with to publish Docker images from a Gitlab CI runner to a private Google Cloud Container Registry.

Create a Service Account

IAM Configuration in the Google Cloud Console

Open IAM. In the sidebar, you’ll see Service Accounts. Create one, with the “Editor” permission set for your project (you may want to be more fine-grained with permissions, but I’m not confident in recommending anything more granular). Be sure to check “Furnish a new key”. You can name it something like “Gitlab CI”.

A service account with Editor role and a new key

Save the key locally when prompted after creation. Be very careful with this key, as it is a literal key to your cloud account (and anyone who gets it can, at minimum, mine some cryptocurrency which you’ll have to pay for… if not worse).

Use a Docker image in Gitlab Runner with Docker-in-Docker

Since you want to use Docker to build your images on the runner, you’ll need to run a Docker image on that runner which has Docker installed. Here’s the first few lines of our .gitlab-ci.yml file:

image: docker:latest
- docker:dind

That sets us up with an environment in which we can run the docker command and build our image. The overlay bit is just a performance improvement, as far as I can gather.

Add the JSON Service Key Secret

Next, we add a Gitlab secret environment variable with the contents of our Service Account’s authentication key which we downloaded previously.

In your Gitlab repo, hover the settings icon in the sidebar and select CI/CD. Expand the ‘Secret variables’ section and add the contents of your key to a variable which you may name yourself (I called mine GCLOUD_SERVICE_KEY):

Gitlab secrets

Now this variable is available in our Gitlab CI environment.

Install GCloud SDK and Log In

In your Gitlab CI config file, add a before_script section which updates and installs some dependencies, then logs into your private registry. Note that I am using the domain for my registry. Don’t log into the wrong registry; the login will succeed, but you will get an authorization error when pushing.

(Also note that I’m not sure every step here is necessary, I copied most of this from a great gist here)

# Install CA certs, openssl to https downloads, python for gcloud sdk
- apk add --update make ca-certificates openssl python
- update-ca-certificates
# Write our GCP service account private key into a file
- echo $GCLOUD_SERVICE_KEY > ${HOME}/gcloud-service-key.json
# Download and install Google Cloud SDK
- wget
- tar zxvf google-cloud-sdk.tar.gz && ./google-cloud-sdk/ --usage-reporting=false --path-update=true
- google-cloud-sdk/bin/gcloud --quiet components update
- google-cloud-sdk/bin/gcloud auth activate-service-account --key-file ${HOME}/gcloud-service-key.json
- docker login -u _json_key --password-stdin < ${HOME}/gcloud-service-key.json

Great, if that succeeded, you should now have access to the Google Cloud Registry. Just to round things out, here’s the rest of my .gitlab-ci.yml file where I build and push my image:

- publish
stage: publish
- docker build -t $IMAGE_NAME .
- docker push "$GCLOUD_PROJECT_ID/$IMAGE_NAME:latest"
- master

… which just builds the image, tags it as Google Cloud expects, then pushes it off. Again, be sure you’re pushing to the correct registry domain and that you’ve defined any variables shown here or substituted hardcoded values as you see fit.

Grant Forrest

Written by

Writes frontend code, short fiction, theological musings.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade