Skip to content

Commit b6ed7c6

Browse files
terchrisclaude
andcommitted
docs: add initializeCommand, update remoteEnv + postStartCommand docs
- Added initializeCommand documentation (hostname capture on host) - Added DEV_HOST_HOSTNAME to remoteEnv example and table - Updated DCT_IMAGE_VERSION example to 1.7.31 - Documented execution order: initializeCommand → ENTRYPOINT → postStartCommand - Removed duplicate init section - Explained per-platform hostname -s behavior Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d8baa9d commit b6ed7c6

1 file changed

Lines changed: 30 additions & 9 deletions

File tree

website/docs/contributors/architecture/devcontainer-json.md

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ VS Code extensions installed automatically when the container starts. These are
127127
"remoteEnv": {
128128
"DCT_HOME": "/opt/devcontainer-toolbox",
129129
"DCT_WORKSPACE": "/workspace",
130-
"DCT_IMAGE_VERSION": "1.7.23",
130+
"DCT_IMAGE_VERSION": "1.7.31",
131131
"DEV_HOST_USER": "${localEnv:USER}",
132132
"DEV_HOST_USERNAME": "${localEnv:USERNAME}",
133133
"DEV_HOST_OS": "${localEnv:OS}",
@@ -136,6 +136,7 @@ VS Code extensions installed automatically when the container starts. These are
136136
"DEV_HOST_LANG": "${localEnv:LANG}",
137137
"DEV_HOST_SHELL": "${localEnv:SHELL}",
138138
"DEV_HOST_TERM_PROGRAM": "${localEnv:TERM_PROGRAM}",
139+
"DEV_HOST_HOSTNAME": "${localEnv:HOSTNAME}",
139140
"DEV_HOST_COMPUTERNAME": "${localEnv:COMPUTERNAME}",
140141
"DEV_HOST_PROCESSOR_ARCHITECTURE": "${localEnv:PROCESSOR_ARCHITECTURE}",
141142
"DEV_HOST_ONEDRIVE": "${localEnv:OneDrive}"
@@ -150,7 +151,7 @@ Environment variables available inside the container. Set by VS Code at containe
150151
|----------|-------|---------|
151152
| `DCT_HOME` | `/opt/devcontainer-toolbox` | Root of the toolbox installation. All scripts reference this. |
152153
| `DCT_WORKSPACE` | `/workspace` | The mounted project directory. Scripts use this instead of hardcoding `/workspace`. |
153-
| `DCT_IMAGE_VERSION` | e.g. `1.7.23` | The image version this devcontainer.json was last updated for. `dev-update` downloads the latest template which has this set by CI. VS Code detects the change and prompts rebuild. |
154+
| `DCT_IMAGE_VERSION` | e.g. `1.7.31` | The image version this devcontainer.json was last updated for. `dev-update` downloads the latest template which has this set by CI. VS Code detects the change and prompts rebuild. |
154155

155156
#### Host detection variables
156157

@@ -285,22 +286,42 @@ Adds a tiny init process (`tini`) as PID 1 inside the container. This properly h
285286

286287
---
287288

288-
### postStartCommand
289+
### initializeCommand
289290

290291
```json
291-
"postStartCommand": "bash /opt/devcontainer-toolbox/additions/config-host-info.sh --verify 2>/dev/null || true"
292+
"initializeCommand": "mkdir -p .devcontainer.secrets/env-vars && hostname -s > .devcontainer.secrets/env-vars/.host-hostname 2>/dev/null || hostname > .devcontainer.secrets/env-vars/.host-hostname 2>/dev/null || true"
292293
```
293294

294-
Runs after VS Code connects to the container, on every start. At this point `remoteEnv` variables (`DEV_HOST_*`) are available.
295+
Runs on the **host machine** before the container starts. This is the only devcontainer lifecycle command that executes outside the container.
296+
297+
Used to capture the host's real hostname, which is not available via `remoteEnv` on macOS (zsh doesn't export `HOSTNAME`). The file `.devcontainer.secrets/env-vars/.host-hostname` is read by `config-host-info.sh` as a fallback when `DEV_HOST_HOSTNAME` is empty.
295298

296-
This refreshes `.devcontainer.secrets/env-vars/.host-info` with correct host detection data (OS, username, Docker engine info). The ENTRYPOINT runs before VS Code injects remoteEnv, so it cannot detect the host — `postStartCommand` fills this gap.
299+
| Platform | What `hostname -s` returns |
300+
|----------|---------------------------|
301+
| macOS | Machine name (e.g., `MBP-J4G0G066W2`) |
302+
| Linux | Machine hostname (e.g., `terje-desktop`) |
303+
| Windows (WSL2) | WSL hostname |
304+
| Windows (PowerShell) | Falls back to `hostname` without `-s` |
297305

298-
**Why not in the entrypoint:** The entrypoint is a Docker-level construct that runs before VS Code connects. `remoteEnv` variables are injected by VS Code after the container starts. Any host detection in the entrypoint sees empty `DEV_HOST_*` variables and writes `unknown`.
306+
The `mkdir -p` ensures the secrets directory exists on fresh installs. The file is in `.devcontainer.secrets/` which is gitignored.
307+
308+
---
309+
310+
### postStartCommand
299311

300312
```json
301-
"init": true
313+
"postStartCommand": "bash /opt/devcontainer-toolbox/additions/config-host-info.sh --verify 2>/dev/null || true"
302314
```
303315

304-
Adds a tiny init process (`tini`) as PID 1 inside the container. This properly handles zombie processes and signal forwarding.
316+
Runs after VS Code connects to the container, on every start. At this point `remoteEnv` variables (`DEV_HOST_*`) are available.
317+
318+
This refreshes `.devcontainer.secrets/env-vars/.host-info` with correct host detection data (OS, username, hostname, Docker engine info). The data is used by OTel telemetry, `dev-env`, and Grafana dashboards.
319+
320+
**Why not in the entrypoint:** The ENTRYPOINT is a Docker-level construct that runs before VS Code connects. `remoteEnv` variables are injected by VS Code after the container starts. Any host detection in the entrypoint sees empty `DEV_HOST_*` variables and writes `unknown`. `postStartCommand` runs after VS Code has set up the environment.
321+
322+
**Execution order on container start:**
323+
1. `initializeCommand` — on host, captures hostname
324+
2. ENTRYPOINT — in container, no remoteEnv (git identity, services, tool install)
325+
3. `postStartCommand` — in container, remoteEnv available (host info detection)
305326

306327
**Must be `true`** — without it, orphaned child processes (from background tools, services, or crashed scripts) accumulate and never get reaped. The init process also ensures `SIGTERM` is forwarded correctly when the container stops, allowing graceful shutdown of services managed by supervisord.

0 commit comments

Comments
 (0)