Reusable Dev Container Features and Templates published to ghcr.io/alindesign.
| Feature | ID | Purpose |
|---|---|---|
| dotfiles | ghcr.io/alindesign/features/dotfiles:1 |
zsh + starship + CLI tools (fd, rg, bat, fzf, jq, delta, eza, zoxide) + nvim + git config |
| mise | ghcr.io/alindesign/features/mise:1 |
mise toolchain manager, shared install at /usr/local/share/mise |
| node | ghcr.io/alindesign/features/node:2 |
Node.js via mise + package manager (pnpm/npm/yarn; pnpm default) |
| go | ghcr.io/alindesign/features/go:1 |
Go via mise, optional go install tools |
| rust | ghcr.io/alindesign/features/rust:1 |
Rust via mise (rustup) with components + targets |
| java | ghcr.io/alindesign/features/java:1 |
Java (Temurin) via mise + optional Maven/Gradle |
| ocaml | ghcr.io/alindesign/features/ocaml:1 |
OCaml via opam (mise has no first-class OCaml plugin) |
| python | ghcr.io/alindesign/features/python:1 |
Python via mise + uv (default) / poetry / pip |
| ansible | ghcr.io/alindesign/features/ansible:1 |
Ansible (+ ansible-lint) via uv tool. Auto-bootstraps Python. |
| bun | ghcr.io/alindesign/features/bun:1 |
Bun runtime + package manager (standalone, no Node required) |
| docker-in-docker | ghcr.io/alindesign/features/docker-in-docker:1 |
Docker Engine + buildx + Compose v2 |
| kubectl | ghcr.io/alindesign/features/kubectl:1 |
kubectl + helm + k9s + kubectx/kubens (each skippable) |
| opentofu | ghcr.io/alindesign/features/opentofu:1 |
OpenTofu + tflint (with terraform → tofu alias) |
| db-tooling | ghcr.io/alindesign/features/db-tooling:1 |
CLI clients: psql + mysql + redis-cli + mongosh (each skippable) |
| secrets | ghcr.io/alindesign/features/secrets:1 |
sops + age + pass for secret management |
| claude | ghcr.io/alindesign/features/claude:1 |
Claude Code CLI via npm. Bootstraps Node if missing. |
| aws-cli | ghcr.io/alindesign/features/aws-cli:1 |
AWS CLI v2 from the official installer |
| gcloud | ghcr.io/alindesign/features/gcloud:1 |
gcloud CLI via Google apt repo (with components option) |
The mise-based features (node, go, java, python) all auto-bootstrap mise if you don't add the mise feature explicitly — they share the same MISE_DATA_DIR so adding more is incremental and cheap. rust uses rustup directly with system-wide RUSTUP_HOME/CARGO_HOME.
If you find yourself always using dotfiles + mise together, skip the layer rebuild by using the pre-baked image:
See images/base/ for what's included.
| Template | ID | Stack |
|---|---|---|
| node | ghcr.io/alindesign/templates/node |
Ubuntu + dotfiles + node (pnpm by default) |
| go | ghcr.io/alindesign/templates/go |
Ubuntu + dotfiles + go + gopls + dlv |
| rust | ghcr.io/alindesign/templates/rust |
Ubuntu + dotfiles + rust (stable + clippy/rustfmt/rust-analyzer) |
| java | ghcr.io/alindesign/templates/java |
Ubuntu + dotfiles + java (Temurin 21) + Maven |
| ocaml | ghcr.io/alindesign/templates/ocaml |
Ubuntu + dotfiles + ocaml (5.2.0 + dune + LSP) |
| python | ghcr.io/alindesign/templates/python |
Ubuntu + dotfiles + python (uv by default) |
| ansible | ghcr.io/alindesign/templates/ansible |
Ubuntu + dotfiles + python (uv) + ansible + ansible-lint |
| claude-dev | ghcr.io/alindesign/templates/claude-dev |
Ubuntu + dotfiles + node + claude + mounts ~/.claude + ~/.claude.json + macOS Keychain dump |
| cloud-ops | ghcr.io/alindesign/templates/cloud-ops |
Ubuntu + dotfiles + aws-cli + gcloud + mounts ~/.aws + ~/.config/gcloud |
| devops | ghcr.io/alindesign/templates/devops |
Full IaC toolbox: dotfiles + python + ansible + aws-cli + gcloud + kubectl + opentofu + secrets + mounts |
| k8s | ghcr.io/alindesign/templates/k8s |
Ubuntu + dotfiles + go + kubectl + docker-in-docker + mount ~/.kube |
| data-science | ghcr.io/alindesign/templates/data-science |
Ubuntu + dotfiles + python (uv) + JupyterLab + DuckDB + db-tooling |
Dev Containers: New Dev Container... → pick a template from alindesign/....
npx -y @devcontainers/cli templates apply \
--template-id ghcr.io/alindesign/templates/node:latest \
--workspace-folder .Pick exactly what you need:
{
"image": "ghcr.io/alindesign/devcontainer-base:latest",
"features": {
"ghcr.io/alindesign/features/node:2": { "packageManager": "pnpm" },
"ghcr.io/alindesign/features/go:1": { "version": "1.23" },
"ghcr.io/alindesign/features/claude:1": {},
"ghcr.io/alindesign/features/aws-cli:1": {},
"ghcr.io/alindesign/features/gcloud:1": {}
},
"remoteUser": "vscode"
}dotfiles + mise are pre-baked into devcontainer-base — don't add them as features unless you want to override a setting.
Features that integrate with host-side accounts (claude, aws-cli, gcloud) declare static mounts in their manifest, so adding the feature automatically wires ~/.claude, ~/.aws, ~/.config/gcloud from the host. The mount targets assume remoteUser: vscode; override in your devcontainer.json if you use a different user.
src/ features (one folder per feature)
test/ `devcontainer features test` scenarios
templates/src/ devcontainer templates
.github/workflows/ release + CI
# Test a single feature
devcontainer features test --features node --base-image mcr.microsoft.com/devcontainers/base:ubuntu .
# Test a template (only after publishing — CLI needs an OCI ref, not a path)
devcontainer templates apply -t ghcr.io/alindesign/templates/node:latest -w /tmp/scratchRequires the devcontainer CLI:
brew install devcontainer
# or
npm install -g @devcontainers/cliEvery push to main triggers .github/workflows/release.yml, which publishes any changed features and templates to ghcr.io/alindesign/... (versions come from each feature/template manifest).
# Bump a feature's version, then:
git commit -am "feat(node): ..."
git push
{ "image": "ghcr.io/alindesign/devcontainer-base:latest", "features": { "ghcr.io/alindesign/features/node:2": { "packageManager": "pnpm" } } }