From 5b5347a5521f147a5c0b504a6d7dd3bfc0cd85ce Mon Sep 17 00:00:00 2001 From: aevesdocker Date: Thu, 25 Jun 2026 10:18:45 +0100 Subject: [PATCH 1/2] Compose: lifecycle hook update Signed-off-by: aevesdocker --- content/manuals/compose/how-tos/lifecycle.md | 34 +++++++++++++++- content/reference/compose-file/services.md | 41 ++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/content/manuals/compose/how-tos/lifecycle.md b/content/manuals/compose/how-tos/lifecycle.md index a5924ae3cfc3..0f9ce1ae51b6 100644 --- a/content/manuals/compose/how-tos/lifecycle.md +++ b/content/manuals/compose/how-tos/lifecycle.md @@ -2,8 +2,8 @@ title: Using lifecycle hooks with Compose linkTitle: Use lifecycle hooks weight: 20 -description: Learn how to use Docker Compose lifecycle hooks like post_start and pre_stop to customize container behavior. -keywords: docker compose lifecycle hooks, post_start, pre_stop, docker compose entrypoint, docker container stop hooks, compose hook commands +description: Learn how to use Docker Compose lifecycle hooks like pre_start, post_start, and pre_stop to customize container behavior. +keywords: docker compose lifecycle hooks, post_start, pre_stop, pre_start, docker compose entrypoint, docker container stop hooks, compose hook commands --- {{< summary-bar feature_name="Compose lifecycle hooks" >}} @@ -22,6 +22,35 @@ Lifecycle hooks are particularly useful because they can have special privileges for security. This means that certain tasks requiring higher permissions can be done without compromising the overall security of the container. +### Pre-start hooks + +Pre-start hooks let you run init containers that must complete successfully before your service starts - database migrations, volume permission fixes, or configuration seeding. Unlike [`post_start`](#post-start-hooks) and [`pre_stop`](#pre-stop-hooks), each `pre_start` step runs in its own ephemeral container before the service container starts. Hooks run once for the service as a whole, not per replica, and won't re-run when you add more replicas of the service. + +A `pre_start` step is skipped on subsequent `docker compose up` runs if it previously succeeded and its definition hasn't changed, but reruns if the definition changes, the previous run failed, or the service is recreated with `--force-recreate`. + +In the following example, two steps run in order before the application starts: database migrations using the service's own image, then a `busybox` container to fix volume ownership. + +```yaml +services: + app: + image: myapp:latest + depends_on: + db: + condition: service_healthy + pre_start: + - command: ["./manage.py", "migrate"] + - image: busybox + command: sh -c 'chown -R 1000:1000 /data' + volumes: + - data:/data + + db: + image: postgres:16 + +volumes: + data: +``` + ### Post-start hooks Post-start hooks are commands that run after the container has started, but there's no @@ -72,5 +101,6 @@ volumes: ## Reference information +- [`pre_start`](/reference/compose-file/services.md#pre_start) - [`post_start`](/reference/compose-file/services.md#post_start) - [`pre_stop`](/reference/compose-file/services.md#pre_stop) diff --git a/content/reference/compose-file/services.md b/content/reference/compose-file/services.md index 9bbe421dc891..eb9a1b0417c2 100644 --- a/content/reference/compose-file/services.md +++ b/content/reference/compose-file/services.md @@ -1752,6 +1752,47 @@ services: For more information, see [Use lifecycle hooks](/manuals/compose/how-tos/lifecycle.md). +### pre_start + +_Todo: Add Compose version_ + +`pre_start` defines a sequence of init containers to run before the service container is started. Each step runs to completion, in declared order, and the service container only starts once every step has exited `0`. A non-zero exit fails the bring-up of the service and its dependents. + +Unlike `post_start` and `pre_stop`, which run a command inside the running service container, each `pre_start` step runs in its own ephemeral container, created after the service container is created but before it is started. Possible values are: + +- `command`: The command to run. Optional when the chosen image's entrypoint already runs the intended command. +- `image`: The image used for the ephemeral container. If omitted, the parent service's image is used. +- `user`: The user to run the command. If not set, defaults to the user declared in `image` (or to the main service command's user when `image` is omitted). +- `privileged`: Lets the `pre_start` command run with privileged access. +- `working_dir`: The working directory in which to run the command. If not set, it is run in the same working directory as the main service command. +- `environment`: Sets the environment variables to run the `pre_start` command. The command inherits the `environment` set for the service's main command, and this section lets you append or override values. +- `per_replica`: Whether the hook runs once for the service as a whole before any replica starts, or once per replica. Defaults to false (once for the service as a whole). + +A `pre_start` container joins the same networks as the service, so it can reach services declared in `depends_on`, and shares the service's declared volume mounts so files it produces in a shared volume are visible to the service. With `per_replica: false` and a scaled service, only mounts that are shared across replicas (named volumes, bind mounts) are usable. Per-instance mounts (`tmpfs`, anonymous volumes) cannot be addressed by a single run. + +A `pre_start` step that has already succeeded for its current definition is not re-run on a subsequent `up`, nor when the service container restarts under its `restart` policy. A step runs again when its definition changes, when the previous run did not succeed, or when the service is recreated. + +```yaml +services: + app: + image: myapp:latest + depends_on: + db: + condition: service_healthy + pre_start: + - command: ["./manage.py", "migrate"] + - image: busybox + command: sh -c 'chown -R 1000:1000 /data' + volumes: + - data:/data + + db: + image: postgres:16 + +volumes: + data: +``` + ### `pre_stop` {{< summary-bar feature_name="Compose pre stop" >}} From 882ba983b808efba11b3e79e754298069e034eec Mon Sep 17 00:00:00 2001 From: aevesdocker Date: Thu, 25 Jun 2026 10:31:37 +0100 Subject: [PATCH 2/2] Compose: lifecycle hook update Signed-off-by: aevesdocker --- content/manuals/compose/how-tos/lifecycle.md | 2 +- content/reference/compose-file/services.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/manuals/compose/how-tos/lifecycle.md b/content/manuals/compose/how-tos/lifecycle.md index 0f9ce1ae51b6..63fc2bde191b 100644 --- a/content/manuals/compose/how-tos/lifecycle.md +++ b/content/manuals/compose/how-tos/lifecycle.md @@ -26,7 +26,7 @@ compromising the overall security of the container. Pre-start hooks let you run init containers that must complete successfully before your service starts - database migrations, volume permission fixes, or configuration seeding. Unlike [`post_start`](#post-start-hooks) and [`pre_stop`](#pre-stop-hooks), each `pre_start` step runs in its own ephemeral container before the service container starts. Hooks run once for the service as a whole, not per replica, and won't re-run when you add more replicas of the service. -A `pre_start` step is skipped on subsequent `docker compose up` runs if it previously succeeded and its definition hasn't changed, but reruns if the definition changes, the previous run failed, or the service is recreated with `--force-recreate`. +A `pre_start` step is skipped on subsequent `docker compose up` runs if it previously succeeded and its definition hasn't changed, but reruns if the definition changes, the previous run failed, or the service is recreated. In the following example, two steps run in order before the application starts: database migrations using the service's own image, then a `busybox` container to fix volume ownership. diff --git a/content/reference/compose-file/services.md b/content/reference/compose-file/services.md index eb9a1b0417c2..9e8988f24c71 100644 --- a/content/reference/compose-file/services.md +++ b/content/reference/compose-file/services.md @@ -1766,7 +1766,7 @@ Unlike `post_start` and `pre_stop`, which run a command inside the running servi - `privileged`: Lets the `pre_start` command run with privileged access. - `working_dir`: The working directory in which to run the command. If not set, it is run in the same working directory as the main service command. - `environment`: Sets the environment variables to run the `pre_start` command. The command inherits the `environment` set for the service's main command, and this section lets you append or override values. -- `per_replica`: Whether the hook runs once for the service as a whole before any replica starts, or once per replica. Defaults to false (once for the service as a whole). +- `per_replica: false`: Whether the hook runs once for the service as a whole before any replica starts. A `pre_start` container joins the same networks as the service, so it can reach services declared in `depends_on`, and shares the service's declared volume mounts so files it produces in a shared volume are visible to the service. With `per_replica: false` and a scaled service, only mounts that are shared across replicas (named volumes, bind mounts) are usable. Per-instance mounts (`tmpfs`, anonymous volumes) cannot be addressed by a single run.