Lifecycle specification

Post-Start Phase

Fast, repeatable hooks that run on every container start to repair ephemeral state, verify prerequisites, and keep lightweight services running.

Applies at
.devcontainer/lifecycle/post-start.d/
Status
Stable

01 Defines

The postStartCommand phase: scripts in post-start.d/ that run every time the container starts, including the first start and every restart.

02 Applies when

  • Runtime state must be true for every session, whether or not anyone attaches.
  • Transient files, sockets, or certificates disappear between starts and need recreating.
  • A lightweight local service the repository expects needs to be running.

03 Boundaries

  • Expensive bootstrap and dependency operations belong in creation-time phases.
  • Shell or profile configuration written once belongs in post-create.
  • Anything needing a developer’s response belongs in post-attach.

Expected behaviour

  1. 01
    Scripts are fast, because they run on every start.
  2. 02
    Scripts check existing state first, so repeated starts do not duplicate processes or work.
  3. 03
    Unavailable access produces a clear warning rather than a long explanation.

Behaviour#

Post-start is the first phase that repeats in normal use: restarting the container returns here without passing through creation again. Everything in it pays that cost on every start, so it holds only work that is cheap and that has to be true for the session to work.

It differs from Post-Attach Phase in audience. Post-start runs for the container whether or not an editor ever connects; post-attach runs for a person who has just arrived. Services and runtime repairs belong here; prompts and guidance belong there.

Good uses

  • Ensuring Redis, LocalStack, or a bazel-remote cache is running when expected locally
  • Recreating transient directories, sockets, or copied certificates under /tmp
  • Checking gh auth status, aws sts get-caller-identity, or docker info and warning clearly

Avoid

  • npm install, pnpm install, dotnet restore, hugo mod tidy, or other expensive bootstrap
  • Shell or profile configuration that only needs writing once
  • Interactive tasks that wait for a developer

Examples#

.devcontainer/lifecycle/post-start.d/10-start-redis.sh
#!/usr/bin/env bash
set -euo pipefail

if ! redis-cli ping >/dev/null 2>&1; then
    redis-server --daemonize yes
fi

The ping guard is the important part: on a restart where Redis is already running, the hook does nothing.