Why does stopping an idle container take the full 10-second timeout?

August 6, 2026 4 answers
Asked by MellowCedar42
On a Linux host, stopping an otherwise idle container can consistently take about 10 seconds. For example: `docker run -d --name sleeper alpine sleep 1000` `time docker stop sleeper` The 10 seconds is Docker's default grace period, but the interesting part is why SIGTERM does not appear to start the shutdown. A process running as PID 1 inside a PID namespace is treated specially by the kernel: signals from outside the namespace are only delivered if that process has installed a handler for them. SIGKILL and SIGSTOP are exceptions, so after the grace period Docker kills the process. You can check whether the container's PID 1 has a signal handler by inspecting `SigCgt` in `/proc//status`. For SIGTERM, bit 15 corresponds to `0x4000`. If that bit is absent, SIGTERM will not be delivered to PID 1 and the container will wait for the full timeout. There are two common fixes, but they solve slightly different problems. Using `exec` in an entrypoint script replaces the shell with the application, allowing the application to receive the stop signal directly. Using `--init` places a small init process such as tini at PID 1; it catches signals and reaps child processes, which is useful when the entrypoint cannot be changed. Also check the image's configured `STOPSIGNAL`, since Docker may send something other than SIGTERM for applications such as nginx or PostgreSQL.

Answers

CrispWillow29
`--init` is the alternative when changing the entrypoint is impractical: `docker run --init ...`. The init process catches signals and reaps orphaned children, so the stop signal has somewhere to land. It does not magically make a slow application shut down faster; an app that needs two seconds will still need about two seconds.
Reply to this answer
QuietHarbor7
The 10 seconds is Docker's normal grace period, not a slow shutdown. Docker sends the configured stop signal first and waits; if the container is still running, it sends SIGKILL. With a simple `alpine sleep 1000` process as PID 1, `sleep` has no signal handler, so the signal from the parent PID namespace is not delivered. It remains alive until SIGKILL arrives.

VividMango18: That distinction matters: saying the process ignores SIGTERM suggests the signal reached it. In this PID-namespace case, the kernel prevents delivery because PID 1 has not registered a handler.

Reply to this answer
SilverLattice3
If you control the entrypoint script, use `exec` for the long-running application. For example, change `nginx -g 'daemon off;'` to `exec nginx -g 'daemon off;'`. Without `exec`, the shell remains PID 1; with it, nginx becomes PID 1 and can handle its shutdown signal directly. This can reduce a stop from roughly 10 seconds to a fraction of a second when the application exits promptly.

BrightOtter61: The important check is not simply whether a shell appears in the command line. Some shells replace themselves with a single simple command, while others remain for scripts involving additional commands. Check which process is actually PID 1.

Reply to this answer
AmberFalcon54
Also inspect the image's stop signal. `docker inspect -f '{{.Config.StopSignal}}' ` shows what Docker will send. nginx commonly uses SIGQUIT for graceful shutdown, while PostgreSQL uses SIGINT. Testing only for a SIGTERM handler can therefore give the wrong diagnosis. A shell that has no handler for either signal can still force the entire grace period on every stop or container recreation.

NeonPebble86: This can add up during deployments: recreating several services repeatedly incurs the grace period for each old container, even when startup is fast.

Reply to this answer

Add your answer

Answers are reviewed before publication.

Related Discussions