The most surprising thing about pushing Docker images to Google Container Registry (GCR) from Drone CI is that you don’t actually need to install Docker on your Drone runner; Drone handles the Docker build and push lifecycle itself.
Let’s see this in action. Imagine you have a simple Go application and you want to build a Docker image for it and push it to GCR whenever you commit to your main branch. Here’s what your .drone.yml might look like:
kind: pipeline
type: docker
name: default
steps:
- name: build-and-push
image: plugins/docker
settings:
repo: gcr.io/your-gcp-project-id/my-app
tags:
- latest
- ${DRONE_COMMIT_SHA}
username:
from_secret: docker_username
password:
from_secret: docker_password
trigger:
branch:
include:
- main
In this pipeline:
kind: pipelineandtype: dockertell Drone this is a standard Docker-based pipeline.- The
plugins/dockerimage is the magic. This plugin is designed to build Docker images and push them to registries. settings.repospecifies the target repository in GCR. Replaceyour-gcp-project-idwith your actual GCP project ID andmy-appwith your desired image name.settings.tagsdefine the tags for the image. We’re pushing bothlatestand the commit SHA for good traceability.usernameandpasswordare crucial for authentication. These should be stored as Drone secrets. For GCR, you’ll typically use a service account.
To authenticate with GCR, you’ll need a Google Cloud service account with the "Storage Admin" role (or a more granular role like "Storage Object Admin" on the GCR bucket). You’ll then generate a JSON key for this service account.
In your Drone repository settings, you’ll create two secrets:
docker_username: For GCR, this is typically_json_key.docker_password: This will be the content of the JSON key file you downloaded from your service account. Make sure to paste the entire content, including-----BEGIN PRIVATE KEY-----and-----END PRIVATE KEY-----.
When Drone runs this pipeline, it doesn’t execute docker build or docker push commands directly on your runner. Instead, the plugins/docker image acts as a specialized tool. It orchestrates the build process using the Docker daemon available to the Drone execution environment (which is usually managed by Drone itself). The plugin then uses the provided credentials to authenticate with GCR and push the built image.
The DRONE_COMMIT_SHA environment variable is automatically provided by Drone and contains the Git commit hash of the current build. This is a common and useful tag for uniquely identifying image versions.
The plugins/docker image handles the complexities of Docker authentication, image layering, and network communication to the registry. You simply provide the target repository, tags, and authentication details. The plugin takes care of the rest, interacting with the Docker daemon to perform the build and then pushing the resulting image layers to GCR.
Here’s what the build process looks like from Drone’s perspective:
- Drone checks out your repository code.
- It spins up a Docker container for the
plugins/dockerimage. - Inside this container, the plugin uses the Docker daemon to build your image based on your
Dockerfile(which should be in the root of your repository, or specified by the plugin’sdockerfilesetting). - Once the image is built locally to the runner, the plugin uses the provided
docker_usernameanddocker_passwordto log in togcr.io. - Finally, it pushes the built image layers to the specified
repoin GCR with the definedtags.
One common point of confusion is how the plugins/docker image accesses the Docker daemon. Drone manages this by ensuring the Docker socket (/var/run/docker.sock) is available to the plugin container, allowing it to issue Docker commands. This is why you don’t need Docker installed on the host machine running the Drone runner itself, and why you don’t need to explicitly run docker build in a commands section of your step.
The next concept you’ll likely encounter is managing image vulnerability scanning after pushing to GCR.