Architecture & Design¶
One Dockerfile, one shared base stage and three published targets. Every image is built natively for amd64 and arm64, then stitched into a single multi-arch tag.
The layer cake¶
flowchart TB
R["rockylinux/rockylinux:10"] --> B["base stage (not published)<br/>IaC · Kubernetes · Ansible · Trivy<br/>Python 3.14 · Node.js LTS · AI CLIs<br/>database clients · shells"]
B --> A["all-devops<br/>+ AWS CLI v2 + SSM plugin<br/>+ Google Cloud SDK"]
B --> W["aws-devops<br/>+ AWS CLI v2 + SSM plugin"]
B --> G["gcp-devops<br/>+ Google Cloud SDK"]
classDef neutral fill:#334155,stroke:#1e293b,color:#fff
classDef base fill:#0891b2,stroke:#0e7490,color:#fff
classDef all fill:#059669,stroke:#047857,color:#fff
classDef aws fill:#ea7a0c,stroke:#c2410c,color:#fff
classDef gcp fill:#2563eb,stroke:#1d4ed8,color:#fff
class R neutral
class B base
class A all
class W aws
class G gcp
Each target is a single extra RUN on top of base, followed by CMD ["/bin/zsh"]. There is no ENTRYPOINT and no multi-stage builder: what gets installed stays installed.
-
Base layer
Everything every image shares: the OS and build tools, Python, Node.js, IaC, Kubernetes, AI agents and database clients.
-
Cloud layers
What the AWS and GCP layers add, how they are installed, and how the CI pipeline builds and publishes them.
-
Comparison
Side-by-side tool matrix, real sizes and a quick decision tree.
Design choices¶
-
Rocky Linux 10
RHEL-compatible, long support lifecycle, RPM repositories for almost every tool here, and official images for both amd64 and arm64.
-
Zsh by default
Oh My Zsh with the
candytheme, kubectl and AWS completion, and handy aliases (k,kg,tfp,aws-ssm…). Bash and fish are there too. -
Native multi-arch
amd64 and arm64 are built on native GitHub runners in parallel, so Apple Silicon and Graviton users get a real arm64 image with no emulation.
-
Always fresh
Rebuilt every Sunday, plus whenever the daily version check finds a new Terragrunt, TFLint, Packer, k9s, ghorg, gcloud or Python release.
What's in every image¶
| Category | Tools |
|---|---|
| Infrastructure as code | Terraform (via tfswitch), Terragrunt, TFLint, Packer |
| Kubernetes | kubectl, Helm 3, k9s |
| Automation | Ansible, ansible-lint, pre-commit, Task (go-task) |
| Security | Trivy (the vulnerability DB downloads on first scan) |
| AI coding agents | Claude Code (claude), OpenAI Codex CLI (codex), GitHub Copilot CLI (copilot), Google Antigravity CLI (agy) |
| Languages | Python 3.14 (compiled from source), Node.js LTS with npm and npx |
| Git | git, GitHub CLI (gh), ghorg |
| Database clients | mongosh (MongoDB 8.0 repo), psql 17, mysql 8.4 |
| Network & utilities | dig, nslookup, nmap, ncat, telnet, curl, wget, lftp, jq, tree, vim, less, zip/unzip |
| Shells | zsh (default), bash, fish |
Cloud CLIs are the only difference between images:
| Tool | all-devops | aws-devops | gcp-devops |
|---|---|---|---|
| AWS CLI v2 + Session Manager plugin | ✅ | ✅ | — |
| boto3, cfn-lint, s3cmd | ✅ | ✅ | — |
| gcloud, gsutil, bq | ✅ | — | ✅ |
docker-credential-gcr, gke-gcloud-auth-plugin |
✅ | — | ✅ |
How the Dockerfile is ordered¶
Docker rebuilds everything after the first changed instruction, so the order matters:
COPY scripts/*.sh /tmp/: every.shfile inscripts/comes in first, so editing any of them invalidates the whole base.- System packages, Python build, pip packages, database clients, Trivy and Oh My Zsh (one big
RUN). - Downloaded binaries: kubectl, Terraform, Terragrunt, TFLint, Packer, Helm, ghorg, k9s, Task.
- Node.js LTS and the four AI CLIs.
- The per-target cloud
RUN.
The full breakdown is on the base layer page.
Sizes¶
These are measured from GHCR. The three images are within 0.5 GB of each other because the shared base makes up most of each one.
| Image | Compressed download | Unpacked on disk (amd64) |
|---|---|---|
| all-devops | ~1.6 GB | ~5.0 GB |
| aws-devops | ~1.55 GB | ~4.6 GB |
| gcp-devops | ~1.5 GB | ~4.6 GB |
arm64 downloads are about 0.05 to 0.1 GB smaller.
Need something slimmer?
Build your own variant from the same Dockerfile. See Customisation.