Skip to content

Latest commit

 

History

History
402 lines (338 loc) · 18.2 KB

File metadata and controls

402 lines (338 loc) · 18.2 KB

Deacon CLI Examples

Each subdirectory under examples/ is fully self‑contained: copy or cd into it and run the shown commands without referencing assets elsewhere in the repo.

Status: which examples pass today

Several of the newer examples are intentionally designed as canaries — they exercise spec-mandated behavior that deacon doesn't fully implement yet. If you run them today and they fail, it's by design.

The single source of truth for which examples are currently blocked on upstream deacon bugs is the tracking issue:

➡️ #74 — Tracking: example scripts blocked on upstream deacon bugs

That issue lists each blocked example, the specific deacon bug it surfaces, and ticks them off as the underlying issues land. Each affected example's own README.md also links to the specific issue(s) it surfaces, as a breadcrumb back to #74.

Workaround for running examples today: most up-based examples currently need --mount-workspace-git-root false (see #67) when run from inside the deacon repo, to avoid silently picking up the repo's own .devcontainer/. Once #67 lands, the workaround is no longer needed.

Index

  • Build: Dockerfile builds, platform targeting, build args, secrets & SSH, Compose service targeting, image reference builds, multi-tag + labels, push/export workflows, feature installation across modes, validation & error scenarios (build/)

  • CLI: CLI-specific features and flags including port forwarding and custom container names (cli/)

  • Container Lifecycle: lifecycle command execution, ordering, variables, skip flags, progress events, and redaction (container-lifecycle/)

  • Exec: command execution semantics covering working directory, user, TTY, and environment (exec/)

  • Observability: JSON logs, standardized spans, and structured fields (observability/)

  • Registry: authentication methods for push/pull operations (registry/)

  • Configuration (configuration/)

    • configuration/basic/ — Minimum viable config
    • configuration/with-variables/${localEnv:VAR} and workspace tokens
    • configuration/extends-chain/ — Chained extends across base/mid/leaf
    • configuration/extends-chain-cycle/ — Cycle detection in extends (two-file + self-extending)
    • configuration/nested-variables/ — Variable substitution into nested objects
    • configuration/secrets-declarative/ — Top-level secrets property with description + documentationUrl
  • Docker Compose (compose/)

    • compose/multiservice-basic/ — App + Redis, shutdownAction: stopCompose
    • compose/multiple-compose-files/dockerComposeFile as an array merging base + override
    • compose/port-events/--ports-events streaming
  • Doctor (doctor/)

    • doctor/host-requirements/ — Realistic CPU/memory/storage check (passes)
    • doctor/host-requirements-failure/ — Unmeetable requirements (text + JSON output)
    • doctor/gpu-host-requirements/hostRequirements.gpu in all three spec shapes (true, "optional", object)
  • Down (down/)

    • down/basic/shutdownAction: stopContainer, --remove, --volumes, --force, --all, idempotency
  • Feature System (features/)

    • features/dependencies-and-ordering/dependsOn / installsAfter resolution
    • features/parallel-install-demo/ — Parallel install levels
    • features/cache-reuse-hint/ — Digest-based caching
    • features/lockfile-demo/devcontainer-lock.json shape
    • features/override-install-order/overrideFeatureInstallOrder forces non-default order
    • features/feature-contributed-lifecycle/ — Feature-declared postCreate/postStart merge with the user's
    • features/feature-env-injection/ — Spec-mandated _REMOTE_USER / _REMOTE_USER_HOME / _CONTAINER_USER / _CONTAINER_USER_HOME during install
    • features/option-sanitization/ — Option-name → env-var name sanitization rules
    • features/oci-digest-pin/ — Feature ref pinned by @sha256: for reproducibility (network)
  • Read-Configuration (read-configuration/)

    • read-configuration/basic/ — Minimal config discovery and output
    • read-configuration/with-variables/ — Variable substitution for local env and workspace folder
    • read-configuration/extends-chain/ — Chained extends across base/mid/leaf configs
    • read-configuration/override-config/ — Apply an override with --override-config
    • read-configuration/features-minimal/ — Local Feature with --include-features-configuration
    • read-configuration/features-additional/ — Inject a Feature via --additional-features
    • read-configuration/compose/ — Config referencing a Docker Compose file
    • read-configuration/legacy-normalization/ — Legacy containerEnv normalized to remoteEnv
    • read-configuration/id-labels-and-devcontainerId/${devcontainerId} via --id-label
    • read-configuration/named-config-search/.devcontainer/<name>/devcontainer.json discovery alongside the default
  • Run-User-Commands (run-user-commands/)

    • run-user-commands/basic/ — Re-execute lifecycle hooks against an existing container; covers --prebuild, --skip-non-blocking-commands, --container-id
  • Set-Up (set-up/)

    • set-up/basic/ — Attach to a vanilla docker run container and layer a devcontainer.json via --config
  • Template Management (template-management/)

    • template-management/minimal-template/ — Minimal template metadata + apply
    • template-management/template-with-options/ — Boolean, string, enum options
    • template-management/templates-apply/ — Driver script for the apply workflow
    • template-management/optional-paths/ — Spec-mandatory optionalPaths field for opt-in files
  • Up (up/)

    • up/basic-image/ — Image-based start
    • up/dockerfile-build/ — Build from Dockerfile
    • up/compose-basic/, up/compose-profiles/ — Compose with optional profiles
    • up/with-features/ — Features installed during up
    • up/lifecycle-hooks/ — All five hooks
    • up/initialize-command/ — Host-side initializeCommand + workspace-trust gate (--trust-workspace, --trust-workspace-persist, DEACON_NO_PROMPT)
    • up/skip-lifecycle/ — Lifecycle skip flags
    • up/prebuild-mode/--prebuild
    • up/dotfiles-integration/ — Dotfiles flags
    • up/additional-mounts/, up/workspace-mount/ — Extra mounts and custom workspaceMount
    • up/remote-env-secrets/--remote-env, --secrets-file
    • up/id-labels-reconnect/, up/remove-existing/ — Reconnect / replace patterns
    • up/gpu-modes/--gpu-availability
    • up/configuration-output/--include-configuration / --include-merged-configuration
    • up/user-env-probe-modes/userEnvProbe four-value matrix on the up side
    • up/wait-for/waitFor enum + --skip-non-blocking-commands cutoff
    • up/container-user-vs-remote-user/containerUser (PID 1) vs remoteUser (lifecycle + exec)
    • up/security-options/init, capAdd, securityOpt, privileged
    • up/override-command/overrideCommand: false runs the image's own CMD
    • up/update-remote-user-uid/ — UID/GID sync to host user (Linux)
    • up/ports-config/forwardPorts string form, portsAttributes sub-fields, otherPortsAttributes, appPort
    • up/image-metadata-merge/ — Image devcontainer.metadata LABEL merged with user config

Quick Start

Build a basic Dockerfile with build args:

cd examples/build/basic-dockerfile
deacon build --workspace-folder . --build-arg FOO=BAR --output-format json

Build with platform targeting and no cache:

cd examples/build/platform-and-cache
deacon build --workspace-folder . --platform linux/amd64 --no-cache

Build with secrets (requires BuildKit):

cd examples/build/secrets-and-ssh
echo "test-secret" > /tmp/secret.txt
deacon build --workspace-folder . --secret id=foo,src=/tmp/secret.txt

Build from a Compose service with custom tags:

cd examples/build/compose-service-target
deacon build --workspace-folder . --image-name myapp:latest

Build from an image reference with labels:

cd examples/build/image-reference
deacon build --workspace-folder . --image-name myimage:latest --label "version=1.0"

Build with multiple tags and push to registry (requires BuildKit):

cd examples/build/basic-dockerfile
deacon build --workspace-folder . \
  --image-name myrepo/app:latest \
  --image-name myrepo/app:v1.0 \
  --push

Build and export to OCI archive (requires BuildKit):

cd examples/build/basic-dockerfile
deacon build --workspace-folder . --output type=oci,dest=app.tar

Validate a configuration example:

cd examples/configuration/basic
deacon config validate . --json

Up Command Examples

Start a basic development container:

cd examples/container-lifecycle/basic
deacon up --workspace-folder . --include-configuration | jq '.containerId'

Start with prebuild mode (CI/CD workflows):

cd examples/container-lifecycle/basic
deacon up --workspace-folder . --prebuild --include-configuration
# Outputs JSON with container ready for caching

Start with dotfiles installation:

cd examples/container-lifecycle/advanced
deacon up --workspace-folder . \
  --dotfiles-repository https://github.com/user/dotfiles \
  --dotfiles-install-command "./install.sh"

Start with additional mounts and remote environment:

cd examples/container-lifecycle/basic
deacon up --workspace-folder . \
  --mount "type=bind,source=/tmp/cache,target=/cache" \
  --remote-env "NODE_ENV=development" \
  --remote-env "DEBUG=true"

Start with secrets file:

cd examples/container-lifecycle/advanced
echo "API_KEY=secret123" > /tmp/secrets.env
deacon up --workspace-folder . --secrets-file /tmp/secrets.env
# Secrets are redacted from logs automatically

Start with BuildKit cache:

cd examples/container-lifecycle/basic
deacon up --workspace-folder . \
  --buildkit auto \
  --cache-from type=registry,ref=myrepo/cache \
  --cache-to type=registry,ref=myrepo/cache

Start with ID labels for reconnection:

cd examples/container-lifecycle/basic
deacon up --workspace-folder . \
  --id-label project=myapp \
  --id-label environment=dev
# Later reconnect with same labels
deacon up --id-label project=myapp --id-label environment=dev --expect-existing-container

Start with skip flags for faster iteration:

cd examples/container-lifecycle/basic
deacon up --workspace-folder . --skip-post-create --skip-post-attach
# Skips lifecycle hooks for faster startup

Start with included merged configuration:

cd examples/container-lifecycle/basic
deacon up --workspace-folder . \
  --include-configuration \
  --include-merged-configuration | jq '.mergedConfiguration'

Start with custom Docker paths and data folders:

cd examples/container-lifecycle/basic
deacon up --workspace-folder . \
  --docker-path /usr/local/bin/docker \
  --container-data-folder /workspace/.devcontainer \
  --user-data-folder ~/.local/share/deacon

Start a container with custom name:

cd examples/cli/custom-container-name
deacon up --container-name my-dev-container --skip-post-create

Explore template assets:

cd examples/template-management/template-with-options
ls -1
cat devcontainer-template.json | jq '.id, .options'

Apply a template with custom options:

cd examples/template-management/templates-apply
mkdir -p /tmp/my-project
deacon templates apply ../template-with-options \
  --output /tmp/my-project \
  --option customName=my-app \
  --option debugMode=true

Run doctor command for system diagnostics:

cd examples/doctor/host-requirements
deacon doctor --workspace-folder .
# Or for JSON output
deacon doctor --workspace-folder . --json | jq '.disk_space'

Test container lifecycle commands (with full up execution):

cd examples/container-lifecycle/basic
# First, inspect the configuration
deacon read-configuration --config devcontainer.json | jq '.onCreateCommand, .postCreateCommand, .postStartCommand, .postAttachCommand'

# Then execute with up command to see lifecycle in action
deacon up --workspace-folder . --include-configuration

Explore lifecycle execution order:

cd examples/container-lifecycle/execution-order
deacon read-configuration --config devcontainer.json | jq -r '
  "1. onCreate: " + (.onCreateCommand | tostring),
  "2. postCreate: " + (.postCreateCommand | tostring),
  "3. postStart: " + (.postStartCommand | tostring),
  "4. postAttach: " + (.postAttachCommand | tostring)
'

Test configuration extends chain:

cd examples/configuration/extends-chain/leaf
deacon read-configuration --config devcontainer.json --include-merged-configuration | jq '.__meta.layers'

Test nested variable substitution:

cd examples/configuration/nested-variables
deacon config substitute --config devcontainer.json --dry-run | jq '.configuration.containerEnv'

Test skip flags behavior:

cd examples/container-lifecycle/non-blocking-and-skip
deacon read-configuration --config devcontainer.json | jq '{
  onCreate: .onCreateCommand,
  postCreate: .postCreateCommand,
  postStart: .postStartCommand,
  postAttach: .postAttachCommand
}'

Analyze progress events structure:

cd examples/container-lifecycle/progress-events
deacon read-configuration --config devcontainer.json | jq '.postCreateCommand'
# Shows named commands that will generate stable command IDs

Verify redaction configuration:

cd examples/container-lifecycle/redaction
deacon read-configuration --config devcontainer.json | jq '.containerEnv'
# Shows environment variables (including sensitive ones that will be redacted)

Start a multi-service compose environment:

cd examples/compose/multiservice-basic
deacon up
deacon exec sh -lc 'echo ok'

Capture port events from a compose service:

cd examples/compose/port-events
deacon up --ports-events 2>&1 | grep "PORT_EVENT:"

Test exec command semantics:

cd examples/exec/semantics
deacon up
deacon exec sh -lc 'pwd'  # Should output /wsp
deacon exec --env FOO=BAR sh -lc 'echo $FOO'  # Should output BAR
deacon down

Examine lockfile structure and path derivation:

cd examples/features/lockfile-demo
cat devcontainer-lock.json | jq '.features | keys'
cat devcontainer-lock.json | jq '.features["ghcr.io/devcontainers/features/node:1"]'

Verify JSON logs with standardized spans:

cd examples/observability/json-logs
export DEACON_LOG_FORMAT=json
deacon config substitute --workspace-folder . --output-format json 2>&1 \
  | jq 'select(.span.name == "config.resolve")'

Notes

Build examples demonstrate Dockerfile-based container builds with build arguments, platform targeting, cache control, and BuildKit features (secrets, SSH) as specified in the containers.dev spec Container Build section. Additional examples showcase Compose service targeting (compose-service-target/), image reference builds (image-reference/), multi-tag support with --image-name, registry push with --push, and OCI archive export with --output. See the containers.dev spec for complete build parity documentation. Specific build capability example directories (under examples/build/):

  • basic-dockerfile/ – Minimal Dockerfile build
  • platform-and-cache/ – Platform selection & cache control
  • secrets-and-ssh/ – BuildKit secrets & SSH forwarding
  • compose-service-target/ – Targeted Docker Compose service image
  • image-reference/ – Extending a referenced base image
  • multi-tags-and-labels/ – Multiple --image-name tags & custom --label injection
  • output-archive/ – Exporting image as OCI archive via --output
  • push/ – Publishing tags to a registry with --push (BuildKit required)
  • push-output-conflict/ – Demonstrates mutual exclusion of --push and --output
  • dockerfile-with-features/ – Feature install during Dockerfile build
  • image-reference-with-features/ – Feature install atop base image
  • compose-with-features/ – Feature install with Compose service build
  • compose-unsupported-flags/ – Demonstrates pre-build rejection of unsupported flags
  • compose-missing-service/ – Error when referenced service does not exist
  • buildkit-gated-feature/ – Example of feature requiring BuildKit-only capability
  • invalid-config-name/ – Validation failure for incorrect config filename
  • duplicate-tags/ – Duplicate tag validation error scenario
  • unwritable-output/ – Failing fast on unwritable --output destination

Container lifecycle examples demonstrate the complete DevContainer lifecycle command execution workflow as specified in the containers.dev spec Lifecycle Execution Workflow. The up command now has full parity with the specification including: JSON output contract, all CLI flags (workspace/config/lifecycle/mount/env/cache/buildkit/dotfiles/security), validation rules, updateContentCommand execution, prebuild mode, ID labels, secrets handling with redaction, image metadata merging, feature-driven builds, compose parity (mount conversion, profiles, remote-env), UID/security options, and data folder management. See the containers.dev spec for complete implementation status (~95% specification compliance).

Doctor examples demonstrate environment diagnostics including host requirements validation (CPU, memory, storage) and real disk space checking using platform-specific APIs as specified in the containers.dev spec Host Requirements section.

Exec examples demonstrate command execution semantics including working directory, user context, TTY allocation, and environment variable handling as specified in the containers.dev spec Exec Command section.

Feature system examples demonstrate dependency resolution, parallel execution levels, digest-based caching, and lockfile support for reproducible builds as specified in the containers.dev spec Feature Installation Workflow, Distribution & Caching sections, and lockfile specifications.

Observability examples demonstrate JSON logging, standardized tracing spans, and structured fields as specified in the containers.dev spec Monitoring and Observability section.

Registry authentication examples demonstrate multiple authentication methods (environment variables, Docker config, command-line options) for push/pull operations with proper error handling and retry logic as specified in the containers.dev spec OCI Registry Integration section.