Docker
Scripting
Container Management
Automation
DevOps

Run a script when docker is stopped

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Running cleanup logic when Docker stops a container is a common operational requirement for flushing logs, releasing locks, or publishing final metrics. The safest place for this logic is usually inside the container process itself, where stop signals can be handled directly. External host hooks can work too, but they add coupling and deployment complexity.

Handling Stop Signals in the Container

When Docker stops a container, it sends SIGTERM to the main process, waits for a grace period, then sends SIGKILL if needed. If your process traps SIGTERM, you can run a script before exit.

bash
1#!/usr/bin/env bash
2set -euo pipefail
3
4cleanup() {
5  echo "running shutdown script"
6  date >> /tmp/shutdown.log
7}
8
9trap cleanup TERM INT
10
11echo "service started"
12while true; do
13  sleep 1
14done

Use this script as container entrypoint so it receives stop signals directly. If you run a child process tree, ensure signals are forwarded correctly.

Dockerfile and Runtime Wiring

A common production setup is an entrypoint script that launches the app and traps termination events. Keep the script short and deterministic.

dockerfile
1FROM alpine:3.20
2RUN apk add --no-cache bash
3COPY entrypoint.sh /entrypoint.sh
4RUN chmod +x /entrypoint.sh
5ENTRYPOINT ["/entrypoint.sh"]

Run and stop to verify behavior:

bash
1docker build -t stop-hook-demo .
2docker run --name stop-hook --rm stop-hook-demo &
3sleep 2
4docker stop stop-hook

If the cleanup action needs external persistence, write to a mounted volume or send data over the network before exit.

Host Side Alternatives with Docker Events

Sometimes you cannot modify the container image. In that case, listen for Docker stop events on the host and trigger a script externally.

bash
1docker events --filter 'event=stop' --format '{{.Actor.Attributes.name}}' |
2while read -r container_name; do
3  echo "container stopped: ${container_name}"
4  ./on-stop.sh "${container_name}"
5done

This pattern is useful for platform level automation, but it is less portable than in container signal handling and usually needs stronger host permissions.

Coordinating Shutdown in Orchestrated Environments

In Kubernetes or other orchestrators, container stop hooks interact with higher level lifecycle rules. For example, a pod termination grace period controls how long your cleanup can run before force termination. Align script runtime with that budget.

You can also use platform lifecycle hooks for additional control, but process signal handling should remain the primary mechanism because it is closest to the app.

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: stop-demo
5spec:
6  terminationGracePeriodSeconds: 30
7  containers:
8    - name: app
9      image: ghcr.io/example/stop-hook-demo:1.0.0
10      lifecycle:
11        preStop:
12          exec:
13            command: ["/bin/sh", "-c", "echo preStop called"]

Test real shutdown timing under load, not only idle conditions. A script that finishes in two seconds locally may take much longer when network storage or remote APIs are involved. Make the cleanup step idempotent so repeated stop signals or retries do not create duplicate side effects. Idempotency turns many operational edge cases into safe no op behavior.

Record cleanup start and end timestamps in logs so operators can verify shutdown behavior quickly during incidents. Clear shutdown telemetry reduces guesswork when containers terminate unexpectedly.

Common Pitfalls

  • Running cleanup in a process that never receives SIGTERM.
  • Using shell wrappers that do not forward signals to child processes.
  • Assuming cleanup always finishes, even when stop timeout is too short.
  • Writing final data to ephemeral paths that disappear after container exit.
  • Depending on host event listeners without monitoring their health.

Summary

  • Prefer in container signal traps for stop time scripting.
  • Keep entrypoint logic minimal and predictable.
  • Test shutdown under realistic timeout settings.
  • Use host level docker events only when image changes are impossible.
  • Persist critical shutdown output to durable storage.

Course illustration
Course illustration

All Rights Reserved.