gcp-devops¶
The shared DevOps base plus the Google Cloud CLI, with gsutil, bq, beta commands and the GKE auth plugin. No AWS tooling.
ghcr.io/jinalshah/devops/images/gcp-devops
What's inside¶
-
Google Cloud layer
- Google Cloud SDK, pinned per build, in
/usr/lib/google-cloud-sdk gcloud,gsutil(Cloud Storage) andbq(BigQuery)- Components:
beta,docker-credential-gcr,gke-gcloud-auth-plugin - Usage reporting turned off
- Google Cloud SDK, pinned per build, in
-
Shared base
- Terraform (tfswitch), Terragrunt, TFLint, Packer
- kubectl, Helm 3, k9s
- Ansible, ansible-lint, pre-commit, Task, Trivy
- Python 3.14, Node.js LTS, Git,
gh, jq claude,codex,copilot,agymongosh,psql17,mysql8.4
Not included: gcloud alpha (install it in a custom image with gcloud components install alpha), kustomize as a separate binary (use kubectl kustomize), yq and the Docker CLI. The full list is in the tool explorer.
Size
About 1.5 GB compressed and 4.6 GB unpacked. That's only slightly smaller than all-devops, because the shared base is most of the size.
Quick start¶
docker run -it --rm \
-v "$PWD":/srv -w /srv \
-v ~/.config/gcloud:/root/.config/gcloud \
ghcr.io/jinalshah/devops/images/gcp-devops:latest
~/.config/gcloud holds your gcloud accounts, active configuration and project, and Application Default Credentials (ADC).
Authentication¶
gcloud and everything else authenticate separately, which is the most common source of confusion:
flowchart LR
L["gcloud auth login<br/>or activate-service-account"] --> G["gcloud, gsutil, bq,<br/>gke-gcloud-auth-plugin"]
A["gcloud auth application-default login<br/>or GOOGLE_APPLICATION_CREDENTIALS"] --> T["Terraform, client libraries,<br/>Ansible modules"]
classDef gcp fill:#2563eb,stroke:#1d4ed8,color:#fff
classDef neutral fill:#334155,stroke:#1e293b,color:#fff
class L,A neutral
class G,T gcp
Sign in once. You can do this on the host, or inside the container with the mount in place:
Then reuse it:
gcloud ignores GOOGLE_APPLICATION_CREDENTIALS for its own commands, so activate the key explicitly. The variable is still useful for Terraform and client libraries.
docker run --rm \
-v "$PWD":/srv -w /srv \
-v /path/to/key.json:/secrets/key.json:ro \
-e GOOGLE_APPLICATION_CREDENTIALS=/secrets/key.json \
ghcr.io/jinalshah/devops/images/gcp-devops:latest \
bash -c 'gcloud auth activate-service-account --key-file=/secrets/key.json &&
gcloud auth list && terraform plan'
Keys are long-lived secrets. Never commit them; prefer Workload Identity Federation in CI.
More detail, including Workload Identity Federation for GitHub Actions, is in the Authentication guide.
Working with GKE¶
The image includes gke-gcloud-auth-plugin, which kubectl uses to fetch tokens for GKE clusters. Keep both ~/.config/gcloud and ~/.kube mounted, because kubectl runs the plugin whenever it needs a token, and the plugin uses your gcloud credentials to get one (caching it under ~/.kube).
sequenceDiagram
participant You
participant gcloud
participant kubectl
participant Plugin as gke-gcloud-auth-plugin
participant GKE
You->>gcloud: container clusters get-credentials
gcloud->>kubectl: writes context to ~/.kube/config
You->>kubectl: kubectl get pods
kubectl->>Plugin: exec credential request
Plugin->>kubectl: token from gcloud credentials
kubectl->>GKE: API call with token
docker run -it --rm \
-v "$PWD":/srv -w /srv \
-v ~/.config/gcloud:/root/.config/gcloud \
-v ~/.kube:/root/.kube \
ghcr.io/jinalshah/devops/images/gcp-devops:latest \
bash -c 'gcloud container clusters get-credentials my-cluster --region europe-west2 &&
kubectl get pods -A'
A kubeconfig written on your host with get-credentials usually works too, as long as ~/.config/gcloud is also mounted. The exception is when gcloud wrote a full host path to the plugin (it does so when the plugin isn't on the host's PATH) or gke-gcloud-auth-plugin.exe on Windows; in that case re-run get-credentials inside the container.
Common tasks¶
docker run --rm \
-v "$PWD":/srv -w /srv \
-v ~/.config/gcloud:/root/.config/gcloud \
ghcr.io/jinalshah/devops/images/gcp-devops:latest \
bash -c 'terraform init && terraform plan -out=tfplan'
The Google provider uses ADC (gcloud auth application-default login).
docker run --rm \
-v "$PWD":/srv -w /srv \
-v ~/.config/gcloud:/root/.config/gcloud \
ghcr.io/jinalshah/devops/images/gcp-devops:latest \
bash -c 'gsutil -m rsync -r ./build gs://my-bucket/releases/ &&
bq ls'
gcloud storage cp / gcloud storage rsync are the newer equivalents of the gsutil commands.
Configure your host's Docker to push to Artifact Registry (the image has no Docker CLI of its own):
The google.cloud.gcp_compute inventory plugin needs requests and google-auth. requests is already in the image, but google-auth isn't, so install it first:
docker run --rm \
-v "$PWD":/srv -w /srv \
-v ~/.config/gcloud:/root/.config/gcloud \
-v ~/.ssh:/root/.ssh:ro \
ghcr.io/jinalshah/devops/images/gcp-devops:latest \
bash -c 'python3 -m pip install --quiet google-auth &&
ansible-playbook -i gcp_compute.yml deploy.yml'
To avoid installing it on every run, bake them into a custom image.
Tips¶
Cache Terraform providers between runs
A host alias
alias gcp-devops='docker run -it --rm -v "$PWD":/srv -w /srv -v ~/.config/gcloud:/root/.config/gcloud -v ~/.kube:/root/.kube -v ~/.ssh:/root/.ssh:ro ghcr.io/jinalshah/devops/images/gcp-devops:latest'
Then run gcp-devops gcloud projects list or gcp-devops kubectl get pods.
Troubleshooting¶
gcloud says there are no credentialed accounts
- Make sure you signed in with
gcloud auth login(or activated a service account) and that~/.config/gcloudis mounted. - Check the mount:
docker run --rm -v ~/.config/gcloud:/root/.config/gcloud ghcr.io/jinalshah/devops/images/gcp-devops:latest ls -la /root/.config/gcloud - With a key file, run
gcloud auth activate-service-account --key-file=.... SettingGOOGLE_APPLICATION_CREDENTIALSalone doesn't sign gcloud in.
You do not currently have an active project
Set it in your configuration, pass it per command, or use an environment variable. Use single quotes so that the variable expands inside the container, not on your host:
kubectl can't reach or authenticate to GKE
executable gke-gcloud-auth-plugin not found: you're using an old image or a different container. The plugin is in current gcp-devops and all-devops images.- Authentication errors: mount
~/.config/gcloudalongside~/.kube, then re-rungcloud container clusters get-credentials. - Check the context:
kubectl config current-context.
Files created in my project are owned by root
Run sudo chown -R "$(id -u):$(id -g)" . afterwards, or chown inside the container as the last step. --user isn't a good fix because Terraform, claude and HOME live under /root, which only root can read. See Root-owned files.