Devcontainer¶
Lifecycle + shell against a project's local .devcontainer/ stack, and scaffolding new devcontainer configs from the
flavour templates published to the local OCI registry. Registry, base image, templates and feature each have their own
submodule (just devcontainer registry|publish); all build-time sources live under ~/.just/devcontainer/.framework/.
All lifecycle recipes are [no-cd] — run them from the project root so the devcontainer CLI finds .devcontainer/. See
just devcontainer for the recipe list.
Day-to-day workflow¶
Open a project's devcontainer:
run chains build → up → shell. The build is a no-op when the image is cached, so re-running is cheap.
Already running, want a second shell:
Run a one-off command:
Tearing down¶
The devcontainer CLI intentionally has no down recipe. To stop and remove the stack, switch modules:
Run it from the project root — same .devcontainer/docker-compose.yml the lifecycle recipes target.
Scaffolding a new devcontainer¶
scaffold republishes the flavour templates to the local registry, applies the chosen flavour into your project via
devcontainer templates apply (substituting the project name), and runs the flavour's init script. Because scaffold
republishes first, edits to the template source under ~/.just/devcontainer/.framework/ are always live — there is no
separate publish step to forget.
cd ~/new-project
just devcontainer scaffold spring-cloud-gcp # name the flavour
just devcontainer scaffold -i # pick via fzf
just devcontainer flavours enumerates what's available. DEVCONTAINER_TARGET overrides the target directory (defaults
to where you invoked just). --variant/-v <tag> scaffolds against a non-default base image variant — publish it first
(just devcontainer publish image -v <tag>), or the container build will fail pulling it.
Re-running scaffold in an existing project is how you pick up framework updates: template-owned files
(.devcontainer/, Justfile, help.md, submodule .just files) are overwritten without further warning; everything
else — your code, the init-script artefacts — is left alone. The confirmation prompt lists what's already in the target;
read it before typing y.
Registry, base image, features¶
Scaffolded projects pull two things from the local OCI registry at build time: the pre-baked base image and the
dotfiles-base feature (SSH agent forwarding, chezmoi refresh, docker + just). registry up starts the registry
(idempotent), publish image builds and pushes the base image (-v <tag> for a non-default variant),
publish features publishes the feature. registry ls shows what's currently published — base image tags plus every
template and feature with its version and description — and the registry serves a web UI at its root
(http://localhost:5001) for browsing the same. Cleanup is automatic: retention policies in the registry config prune
superseded template/feature versions and garbage-collect their blobs; there is nothing to run.
publish features is deliberate, not automatic: a new feature version invalidates the feature layer in every project's
build cache, so the next rebuild of each project redoes those layers. Run it when you actually change the base plumbing
under ~/.just/devcontainer/.framework/features/.
If a first build/up fails pulling localhost:5001/..., run just devcontainer registry up, publish image, and
publish features first.
Gotchas¶
- Run from the project root. All lifecycle recipes are
[no-cd]. From elsewhere, the devcontainer CLI won't find your.devcontainer/directory and the recipe will fail. runrequires the image to build cleanly. First-time builds can be slow and surface project-specific Docker errors. Ifrunfails, tryjust devcontainer buildto isolate the build from the start phase.scaffoldmutates the current directory. It writes.devcontainer/, aJustfile, and may write project init artefacts — and it overwrites template-owned files without per-file prompts. Run it in a fresh project directory or commit before invoking.scaffoldneeds the docker daemon. It republishes templates to the local registry before applying; with docker down it fails at the registry bring-up, not at file-copying.scaffold -irequiresfzf. Without it, pass the flavour name as a positional argument.- The registry must allow insecure localhost:5001. See the header comment in the module's
.framework/registry/docker-compose.ymlfor the colima configuration.