Tool Basics¶
A quick, practical reference for every tool in the images: what it's for, which image has it, and the commands you'll reach for most.
Want to search and filter the full list instead? Open the interactive tool explorer.
-
Infrastructure as code
Terraform (via tfswitch), Terragrunt, TFLint, Packer
-
Kubernetes
kubectl, Helm 3, k9s
-
Cloud CLIs
AWS CLI v2 + Session Manager, Google Cloud CLI + GKE auth plugin
-
Automation
Ansible, ansible-lint, pre-commit, Task, make
-
Security
Trivy for images, filesystems, IaC and secrets
-
Git & collaboration
Git, GitHub CLI (
gh), ghorg -
Languages
Python 3.14 with pip packages, Node.js LTS with npm and npx
-
AI coding agents
Claude Code, OpenAI Codex CLI, GitHub Copilot CLI, Antigravity CLI (
agy) -
Database clients
mongosh, psql 17, mysql 8.4
-
Network & diagnostics
dig, nmap, ncat, telnet, curl, wget, lftp, openssl, ssh
-
Shells & aliases
Zsh (Oh My Zsh, default), Bash, Fish, plus handy
tf*andk*aliases -
Everyday utilities
jq, zip/unzip, tar, vim, less, tree, bubblewrap
Which image has what?¶
Every tool on this page is in all three images unless its Available in line says otherwise. Only the cloud layers differ:
| Tool | all-devops | aws-devops | gcp-devops |
|---|---|---|---|
| Shared base (everything else on this page) | |||
| AWS CLI v2, Session Manager plugin | |||
| boto3, cfn-lint, s3cmd, crcmod, pytest, requests, bs4, lxml | |||
Google Cloud CLI (gcloud, gsutil, bq) |
|||
gcloud components: beta, docker-credential-gcr, gke-gcloud-auth-plugin |
Not in the images
These are sometimes assumed but are not installed, so add them yourself if you need them: the Docker CLI or daemon (no Docker-in-Docker), standalone kustomize (use kubectl kustomize or kubectl apply -k), yq, pipx, terraform-docs, redis-cli, Go, Java and gcloud alpha.
Infrastructure as code¶
Terraform¶
Declarative infrastructure provisioning for any cloud.
Available in: all three images · latest release at build time, installed with tfswitch
# Workspaces
terraform workspace new staging
terraform workspace select staging
# Variable files and non-interactive apply (CI)
terraform plan -var-file="prod.tfvars" -out=tfplan
terraform apply tfplan
# Target a single resource
terraform apply -target=aws_instance.example
# Bring existing infrastructure under management
terraform import aws_instance.example i-1234567890abcdef0
Shortcuts
The shells ship with tf, tfi, tfp, tfa, tfd, tff, tfv and tfo aliases. See shell aliases.
Terragrunt¶
A thin wrapper around Terraform for DRY configuration, remote state and multi-module stacks.
Available in: all three images · pinned per build, bumped automatically
# Skip interactive prompts (CI)
terragrunt run --all apply --non-interactive
# Include dependencies that live outside the current directory
terragrunt run --all apply --queue-include-external
# Validate every module
terragrunt run --all validate
# Show the dependency graph (DOT format)
terragrunt dag graph
Old commands are gone
Recent Terragrunt releases replaced the old CLI. run-all is now run --all, --terragrunt-non-interactive is --non-interactive, graph-dependencies is dag graph, and --terragrunt-include-external-dependencies is --queue-include-external.
TFLint¶
A Terraform linter that catches errors, deprecated syntax and provider-specific mistakes before plan.
Available in: all three images · pinned per build, bumped automatically
tflint --init # install the plugins listed in .tflint.hcl
tflint # lint the current directory
tflint --recursive # lint every module below here
tflint --config=.tflint.hcl
tflint --format=compact # also: json, checkstyle, junit, sarif
tflint --enable-rule=terraform_naming_convention
Packer¶
Builds machine images (AMIs, GCE images and more) from one template.
Available in: all three images · pinned per build, bumped automatically
Note
Packer's docker builder needs a Docker daemon, which the images don't include. Cloud builders such as amazon-ebs and googlecompute work fine.
Kubernetes¶
kubectl¶
The Kubernetes command-line client.
Available in: all three images · latest stable release at build time, installed at /usr/local/bin/kubectl
# Apply manifests (a file, a directory, or a kustomization)
kubectl apply -f deployment.yaml
kubectl apply -f ./manifests/
kubectl apply -k ./overlays/prod
kubectl kustomize ./overlays/prod # render without applying
# Day-2 operations
kubectl scale deployment/nginx --replicas=5
kubectl rollout status deployment/nginx
kubectl rollout undo deployment/nginx
kubectl port-forward svc/nginx 8080:80
# Needs metrics-server in the cluster
kubectl top nodes
kubectl get events --sort-by='.lastTimestamp'
# Reuse your host kubeconfig
docker run -it --rm -v ~/.kube:/root/.kube \
ghcr.io/jinalshah/devops/images/all-devops:latest
# EKS (aws-devops, all-devops)
aws eks update-kubeconfig --name my-cluster --region eu-west-2
# GKE (gcp-devops, all-devops): uses the bundled gke-gcloud-auth-plugin
gcloud container clusters get-credentials my-cluster --region europe-west2
Shortcuts
k, kg, kd, kl, ka and kr are aliases for kubectl, get, describe, logs, apply and run, and kubectl tab-completion is enabled in Zsh and Bash.
Helm¶
The Kubernetes package manager.
Available in: all three images · latest Helm 3 release at build time
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm search repo prometheus
helm install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring --create-namespace
helm list -A
helm upgrade monitoring prometheus-community/kube-prometheus-stack -n monitoring
helm uninstall monitoring -n monitoring
# Inspect and override values
helm show values prometheus-community/prometheus > values.yaml
helm install prom prometheus-community/prometheus -f values.yaml
helm install prom prometheus-community/prometheus --set server.replicaCount=2
# Render locally or preview an install
helm template prom prometheus-community/prometheus -f values.yaml
helm install prom prometheus-community/prometheus --dry-run --debug
# History and rollback
helm history prom
helm rollback prom 1
# Author your own chart
helm create my-chart
helm lint my-chart
helm package my-chart
The stable repo is gone
https://charts.helm.sh/stable was deprecated years ago and no longer receives updates. Use the project's own chart repository (for example prometheus-community) or an OCI registry instead.
k9s¶
A terminal UI for watching and managing Kubernetes clusters.
Available in: all three images · pinned per build, bumped automatically
k9s # current context
k9s -n kube-system # start in a namespace
k9s --context my-cluster
k9s --readonly # disable modifying commands
Inside k9s, type :pods, :svc, :deploy or :ns to switch views, / to filter, L for logs, D to describe, E to edit, ? for help and Ctrl+C to quit.
Cloud CLIs¶
AWS CLI v2¶
Available in: all-devops aws-devops
# S3
aws s3 cp file.txt s3://my-bucket/
aws s3 sync ./site s3://my-bucket/site --delete
# Filter and project with JMESPath
aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=running" \
--query 'Reservations[].Instances[].[InstanceId,Tags[?Key==`Name`]|[0].Value]' \
--output table
# CloudFormation (lint templates first with cfn-lint)
cfn-lint template.yaml
aws cloudformation deploy --stack-name my-stack --template-file template.yaml
# SSM Parameter Store
aws ssm get-parameter --name /my/parameter --with-decryption
# Per-command profile and region
aws s3 ls --profile production --region eu-west-2
The AWS layer also adds s3cmd, and the Python packages boto3, cfn-lint, crcmod, pytest, requests, bs4 and lxml. aws tab-completion is enabled in Zsh and Bash.
AWS Session Manager plugin¶
Shell access and port forwarding to EC2 instances without SSH keys or bastion hosts.
Available in: all-devops aws-devops
# Interactive shell (the aws-ssm alias does the same thing)
aws ssm start-session --target i-1234567890abcdef0
aws-ssm i-1234567890abcdef0
# Forward local port 8080 to port 80 on the instance
aws ssm start-session --target i-1234567890abcdef0 \
--document-name AWS-StartPortForwardingSession \
--parameters '{"portNumber":["80"],"localPortNumber":["8080"]}'
Tip
The plugin listens on the container's own localhost, so publishing the port with docker run -p may not reach it from your host. Use the forwarded port from inside the container, or try --network host on Linux. To reach RDS or other private endpoints, use AWS-StartPortForwardingSessionToRemoteHost and add "host":["..."] to the parameters.
Google Cloud CLI¶
gcloud, gsutil and bq, plus the beta, docker-credential-gcr and gke-gcloud-auth-plugin components. The SDK lives in /usr/lib/google-cloud-sdk.
Available in: all-devops gcp-devops
# Service account (gcloud itself ignores GOOGLE_APPLICATION_CREDENTIALS)
gcloud auth activate-service-account --key-file=/secrets/sa.json
# Cloud Storage
gcloud storage buckets create gs://my-bucket --location=europe-west2
gcloud storage cp file.txt gs://my-bucket/
gsutil ls gs://my-bucket/
# BigQuery
bq ls
bq query --use_legacy_sql=false 'SELECT 1'
# Named configurations
gcloud config configurations create production
gcloud config configurations activate production
GKE works out of the box
The gke-gcloud-auth-plugin component is installed, so gcloud container clusters get-credentials writes a working kubeconfig and kubectl, helm and k9s can talk to GKE straight away.
Note
gcloud alpha commands are not installed. gcloud beta is.
Automation¶
Ansible¶
Agentless configuration management and orchestration with YAML playbooks.
Available in: all three images · installed with pip, alongside jmespath (for json_query) and paramiko
ansible-playbook playbook.yml -e "version=1.2.3 env=production"
ansible-playbook playbook.yml --limit webserver01
ansible-playbook playbook.yml --tags "configure,deploy" --skip-tags "tests"
ansible-playbook playbook.yml -vvv
# Secrets
ansible-vault encrypt secrets.yml
ansible-playbook playbook.yml --ask-vault-pass
# Collections
ansible-galaxy collection install -r requirements.yml
Tip
Mount your SSH keys read-only (-v ~/.ssh:/root/.ssh:ro) so Ansible can reach your hosts.
ansible-lint¶
Checks playbooks and roles against best practices. yamllint is installed with it as a dependency, so you can run it directly too.
Available in: all three images
ansible-lint # lint the current project
ansible-lint playbook.yml
ansible-lint -L # list rules
ansible-lint --fix # apply automatic fixes
# Skip rules by name
ansible-lint -x command-instead-of-module,no-changed-when playbook.yml
yamllint .
Warning
Numeric rule IDs such as 301 and 302 were removed. Use rule names (command-instead-of-module, no-changed-when and so on), either with -x or in .ansible-lint.
pre-commit¶
Runs linters and formatters as Git hooks.
Available in: all three images
pre-commit install # add the hook to .git/hooks
pre-commit run --all-files
pre-commit run terraform_fmt --all-files # one hook, by id
pre-commit autoupdate
pre-commit uninstall
Task (go-task) and make¶
Task is a YAML-based task runner; GNU make is there too.
Available in: all three images · Task is the latest release at build time
version: '3'
vars:
ENV: dev
tasks:
fmt:
desc: Format Terraform code
cmds:
- terraform fmt -recursive
validate:
desc: Validate Terraform
cmds:
- terraform validate
plan:
desc: Plan for an environment
cmds:
- terraform plan -var-file=envs/{{.ENV}}.tfvars
apply:
desc: Apply for an environment
deps: [validate]
cmds:
- terraform apply -var-file=envs/{{.ENV}}.tfvars
Security¶
Trivy¶
Scans container images, filesystems, repositories and IaC for vulnerabilities, misconfigurations and secrets.
Available in: all three images · installed from Aqua's yum repository
# Fail CI on serious findings only
trivy image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed nginx:latest
# Output formats
trivy image --format json -o results.json nginx:latest
trivy image --format sarif -o results.sarif nginx:latest
# Custom Rego checks for IaC
trivy config --config-check ./checks ./terraform/
# Compliance report
trivy image --compliance docker-cis-1.6.0 nginx:latest
# Clear caches and the downloaded databases
trivy clean --all
First scan downloads the database
No vulnerability database is baked into the image, so the first scan in a fresh container downloads it. Mount a cache to reuse it: -v ~/.cache/trivy:/root/.cache/trivy.
No Docker daemon needed
There is no Docker in the image, so trivy image pulls the image straight from the registry. For private registries, log in with trivy registry login or set TRIVY_USERNAME and TRIVY_PASSWORD.
Git and collaboration¶
Git¶
Available in: all three images
git clone git@github.com:owner/repo.git
git switch -c feature/my-change
git add -p
git commit -m "Describe the change"
git push -u origin feature/my-change
git log --oneline --graph -20
Tip
Mount ~/.ssh:/root/.ssh:ro and ~/.gitconfig:/root/.gitconfig:ro so commits carry your identity and SSH remotes work.
GitHub CLI (gh)¶
Available in: all three images
gh pr checkout 123
gh pr review 123 --approve
gh pr merge 123 --squash --delete-branch
# GitHub Actions
gh workflow list
gh workflow run image-builder.yml
gh run watch
# Releases and raw API calls
gh release create v1.0.0 --generate-notes
gh api /users/jinalshah/packages/container/devops%2Fimages%2Fall-devops/versions --jq '.[0].metadata.container.tags'
ghorg¶
Clones every repository in a GitHub organisation or user account (GitLab, Bitbucket and Gitea too).
Available in: all three images · pinned per build, bumped automatically
export GHORG_GITHUB_TOKEN=ghp_or_fine_grained_token
ghorg clone my-org
ghorg clone my-username --clone-type=user
ghorg clone my-org --protocol=ssh
ghorg clone my-org --path=/srv/repos
# Running the same clone again pulls updates into existing clones
ghorg clone my-org
ghorg ls
A sample config is pre-installed at ~/.config/ghorg/conf.yaml. ghorg reclone runs named clone commands that you define in ~/.config/ghorg/reclone.yaml; it isn't a "refresh" command.
Languages¶
Python 3.14¶
Python 3.14.7 is compiled from source and set as the default python3.
Available in: all three images
| Pip package | Available in |
|---|---|
ansible, ansible-lint (with yamllint), jmespath, paramiko, pre-commit |
all three images |
zensical, mkdocs-material (documentation sites) |
all three images |
boto3, cfn-lint, s3cmd, crcmod, pytest, requests, bs4, lxml |
all-devops aws-devops |
python3 --version
python3 -m pip list
python3 -m pip install -r requirements.txt
# Virtual environments
python3 -m venv .venv
source .venv/bin/activate
# Preview a Zensical docs site from the container
zensical serve -a 0.0.0.0:8000
Use python3 -m pip
A bare pip may belong to the distribution's own Python rather than 3.14. python3 -m pip always installs into the interpreter you'll run.
Note
For zensical serve, publish the port (docker run -p 8000:8000 ...) and bind to 0.0.0.0 as shown so your browser can reach it.
Node.js LTS¶
The current Node.js LTS release from NodeSource (not pinned to a major version), with npm and npx.
Available in: all three images
node --version
npm --version
npm ci # install from package-lock.json
npm run build
npx some-cli --help # run a package without installing it globally
AI coding agents¶
All four are agentic coding assistants: they read and edit files and run commands, interactively or from scripts. Each needs its own account or API key. For full setup, see AI CLI setup.
Available in: all three images
| CLI | Command | Sign in | Script or CI | Mount to keep the login |
|---|---|---|---|---|
| Claude Code | claude |
/login inside claude |
claude -p "..." with ANTHROPIC_API_KEY |
~/.claude |
| OpenAI Codex CLI | codex |
codex login |
codex exec "..." with CODEX_API_KEY |
~/.codex |
| GitHub Copilot CLI | copilot |
/login inside copilot |
copilot -p "..." --allow-all-tools with COPILOT_GITHUB_TOKEN |
~/.copilot |
| Antigravity CLI | agy |
Google sign-in on first run | agy -p "..." |
~/.gemini |
claude # interactive; run /login the first time
claude -p "Explain what main.tf creates"
git diff | claude -p "Review this diff for security issues"
cat plan.txt | claude -p "Summarise this Terraform plan" --output-format json
claude -c # continue the last conversation
There is no --file flag: pipe content in, or name the path in the prompt. Always use -p in scripts, because without it claude opens the interactive UI.
copilot # interactive; run /login the first time
export COPILOT_GITHUB_TOKEN=github_pat_... # fine-grained PAT with "Copilot Requests"
copilot -p "Write a Makefile target that runs tflint" --allow-all-tools
This is the standalone agentic Copilot CLI, not the old gh copilot extension. Classic ghp_ tokens aren't supported.
agy # interactive; prints a sign-in URL, paste the code back
agy -p "Explain this Helm chart"
git diff | agy -p "Review this diff"
agy -p "Summarise the repo" --output-format json --print-timeout 5m
agy --version
Antigravity CLI replaces Google's Gemini CLI. For headless use with a Gemini API key, set {"modelProvider": "gemini"} in ~/.gemini/antigravity-cli/settings.json and export GEMINI_API_KEY; the variable alone isn't enough.
Mount the config directories to keep logins between runs:
docker run -it --rm \
-v "$PWD":/srv -w /srv \
-v ~/.claude:/root/.claude \
-v ~/.codex:/root/.codex \
-v ~/.copilot:/root/.copilot \
-v ~/.gemini:/root/.gemini \
ghcr.io/jinalshah/devops/images/all-devops:latest
Treat these directories like passwords
They hold OAuth tokens and API keys. Don't bake them into images or commit them, and prefer environment variables from your CI secret store in pipelines.
Database clients¶
Available in: all three images
psql -h db.example.com -U app -d appdb
psql "postgresql://app@db.example.com:5432/appdb?sslmode=require"
psql -h db.example.com -U app -d appdb -c "SELECT version();"
psql -h db.example.com -U app -d appdb -f migration.sql
Inside psql: \l lists databases, \c db connects, \dt lists tables, \d table describes one, \q quits.
Reaching a database on your host
From a container, localhost is the container itself. Use host.docker.internal on Docker Desktop, or run with --network host on Linux.
Network and diagnostics¶
Available in: all three images
curl -sSfL https://example.com -o page.html
curl -s https://api.github.com/repos/jinalshah/devops-images | jq '.stargazers_count'
wget -c https://example.com/large-file.zip # resume a download
# Inspect a certificate
openssl s_client -connect example.com:443 -servername example.com </dev/null \
| openssl x509 -noout -subject -issuer -dates
ncat can't scan ranges
ncat -zv host 20-100 does not scan ports 20 to 100. Use ncat -zv host 443 for a single port and nmap -p 20-100 host for a range.
Shells and aliases¶
Available in: all three images
- Zsh is the default shell (
CMD ["/bin/zsh"]), with Oh My Zsh and thecandytheme. The prompt looks likeroot@<host> [HH:MM:SS] [/srv]followed by-> #(Zsh shows#because you're root). - Bash has a coloured prompt and bash-completion. Start it with
bash, or run one-off commands withdocker run ... bash -c "...". - Fish is installed but not configured; start it with
fish.
Shell aliases¶
These are defined in both ~/.zshrc and ~/.bashrc (from scripts/10-zshrc.sh and scripts/20-bashrc.sh). Fish has none of them.
| Alias | Expands to | Alias | Expands to | |
|---|---|---|---|---|
tf |
terraform |
k |
kubectl |
|
tfi |
terraform init |
ka |
kubectl apply |
|
tfp |
terraform plan |
kd |
kubectl describe |
|
tfa |
terraform apply |
kg |
kubectl get |
|
tfd |
terraform destroy |
kl |
kubectl logs |
|
tff |
terraform fmt -recursive |
kr |
kubectl run |
|
tfv |
terraform validate |
aws-ssm |
aws ssm start-session --target |
|
tfo |
terraform output |
ll / la / l |
ls -alF / ls -A / ls -CF |
Both shells also enable tab-completion for kubectl, and for aws in the images that include the AWS CLI.
Note
Aliases only exist in interactive shells. In docker run ... <command> or CI steps, use the full command names.
Everyday utilities¶
Available in: all three images