Canonical dev container template for the musher-dev organization. Batteries-included configuration with AI CLIs, multiple language runtimes, Docker-in-Docker, Task runner, and consistent VS Code settings. Comment out what you don't need.
- Ubuntu base with zsh/oh-my-zsh
- Node, Python, Go runtimes
- Docker-in-Docker
- Git + GitHub CLI
- Claude CLI + Codex CLI + Task runner
- GitLens, YAML, TOML, Copilot, Go, Python, Ruff, ESLint, Docker extensions
- Format on save, rulers, trailing whitespace trimming
- Click Use this template → Create a new repository on GitHub
- Clone your new repo and open in VS Code
- Command Palette → Dev Containers: Reopen in Container
- (Optional) Edit
.devcontainer/.envto setCOMPOSE_PROFILESand override credentials — the file is created automatically from.env.exampleon first build.
All local-dev state is contained under .devcontainer/. On first build, initializeCommand copies .env.example → .env (gitignored). The same file feeds:
- Docker Compose — auto-discovered as the sibling
.envnext tocompose.yaml, used to interpolate${VAR:-default}references. - The dev container itself — loaded via
runArgs --env-file, so shells and runtimes inside the container see the same values.
To reset local env state, delete .devcontainer/.env and rebuild. Useful task commands:
| Command | Purpose |
|---|---|
task env:check |
Verify .env has every key from .env.example. |
task env:required |
List required keys (declared empty in the template) that still need a value. |
task env:diff |
Show keys present in one of .env / .env.example but not the other. |
task env:reset |
Re-copy the template over .env (prompts before overwriting). |
The startup MOTD also warns about drift or unfilled required keys.
- Comment out unneeded features/extensions in
devcontainer.json - Add project setup to
scripts/post-create.sh(runs afterbase_setup) - Enable optional services via
COMPOSE_PROFILESin.devcontainer/.env(redis, minio, registry, azimutt, observability) - Full reference → CONFIGURATION.md
This template includes .github/workflows/validate.yaml which runs ShellCheck, Compose config validation, and a devcontainer build check. Keep or remove per your project's needs.
The postCreateCommand automatically strips \r from all scripts before running them. If you add new scripts, ensure they're under .devcontainer/scripts/ to be included.
If settings aren't applying after changes, rebuild without cache:
Command Palette → Dev Containers: Rebuild Container Without Cache
Named volumes may initialize with root ownership. The ensure_writable_dir function in common.sh and the base_setup_config_dirs step handle this for base volumes. For custom volumes, call ensure_writable_dir in your post-create.sh:
ensure_writable_dir /home/vscode/.my-toolBase setup uses retry with 3 attempts and 5-second delays for network operations. If a tool consistently fails to install, check network connectivity and try rebuilding the container.