Podman Stop Timeout and PID 1
`podman stop` on a container running `sleep` takes 10.119 seconds and ends in SIGKILL. The same image with `--init` takes 0.099 seconds, because the kernel does not apply default signal handlers to PID 1.
Containers and Images Guide 10 of 47 Intermediate
- OSUbuntu 26.04 LTS (resolute)
- Podman5.7.0
- Runtimecrun 1.21
- Networknetavark 1.16.1
- TimeAbout 14 min
- Reviewed22 August 2026
Written against the versions above. Podman follows the distribution here rather than a vendor repository, so the version you get is the one Ubuntu shipped. The commands are stable across 5.x.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| PODMAN01 | 192.168.0.24 | Ubuntu 26.04 LTS | Primary Container Host | 2 Core | 4 GB | 50 GB |
Before you start
- Podman installed - see guide 1.
- Nothing else; every container here is
alpinewith a shell command.
-
Ten seconds to stop a sleep
Start
sleep 300and stop it. Time it.level=warning msg="StopSignal SIGTERM failed to stop container nosig in 10 seconds, resorting to SIGKILL" real 0m10.119ssleepis not broken and Podman is not slow.psinside showssleepas PID 1, and that is the whole explanation.The kernel treats PID 1 specially: default signal dispositions do not apply to it. Anywhere else, a process with no SIGTERM handler is killed by the kernel's default action. As PID 1, a signal with no explicit handler is simply discarded. So SIGTERM arrives, nothing happens, Podman waits out its timeout and sends SIGKILL, which cannot be ignored by anyone.
Every container image whose entrypoint is a plain binary that never installed a signal handler behaves this way.
bash Example session podman run -d --name nosig docker.io/library/alpine sleep 300d5d665f80d250fa1b8b2b65d8585eb59c08a7a0dbd9912acb48cf235c5440d98podman exec nosig ps -eo pid,commPID COMMAND 1 sleep 2 pstime podman stop nosigtime="2026-08-22T11:32:00Z" level=warning msg="StopSignal SIGTERM failed to stop container nosig in 10 seconds, resorting to SIGKILL"nosig real 0m10.119suser 0m0.083ssys 0m0.087sExpected result
sleepas PID 1, the SIGKILL warning, and about 10 seconds.Success conditionYou have measured the ten seconds and can name what caused it.
-
The same command, one hundred times faster
Add
--init. Nothing else changes - same image, samesleep 300.PID COMMAND 1 podman-init 2 sleep real 0m0.099s0.099 seconds against 10.119.
sleepis now PID 2, so it is an ordinary process and the kernel's default SIGTERM action applies. It dies immediately.PID 1 is
podman-init- thecatatonitbinary that arrived as a dependency in guide 1. It does the two jobs a real init does: forwards signals to its child, and reaps orphaned processes so they do not accumulate as zombies.This is the fix to reach for when you do not control the image. It costs one flag and a few hundred kilobytes.
bash Example session podman run -d --name withinit --init docker.io/library/alpine sleep 30037a7e00f038fc5ea1a01f25dbfc3cacc1a43d50325c72eef2a41962913e01760podman exec withinit ps -eo pid,commPID COMMAND 1 podman-init 2 sleep 3 pstime podman stop withinitwithinit real 0m0.099suser 0m0.013ssys 0m0.021sExpected result
podman-initas PID 1 withsleepas PID 2, and a stop under a tenth of a second.Success conditionYou have made the same workload stop instantly by changing its PID.
-
Or handle the signal, if the process is yours
When you own the entrypoint, the better fix is to handle SIGTERM rather than work around not handling it.
A shell with
trap "echo caught SIGTERM; exit 0" TERMstops in 0.783 seconds, andpodman logsproves it was a graceful exit rather than a lucky one:caught SIGTERMThat is the difference that matters in production. SIGKILL gives a process no opportunity to finish a request, flush a buffer or close a connection cleanly. A handled SIGTERM does.
Two related traps worth knowing.
sh -c "myapp"often leaves the shell as PID 1 with your app as a child, so the shell discards the signal and your app never hears it - useexec myappso the app replaces the shell. And in a Containerfile,CMD myapp(shell form) wraps it in/bin/sh -c, whileCMD ["myapp"](exec form) does not.bash Example session podman run -d --name trapper docker.io/library/alpine sh -c 'trap "echo caught SIGTERM; exit 0" TERM; while true; do sleep 1; done'6aebb4923ecf569cd10358249225a47209ca5126b53bda5ae8a47cf27a19702atime podman stop trappertrapper real 0m0.783suser 0m0.026ssys 0m0.014spodman logs trappercaught SIGTERMExpected resultA stop under a second, and
caught SIGTERMin the logs.Success conditionYou have a container that exits on request rather than being killed.
-
Shortening the wait is not the same as fixing it
--stop-timeout 2gets you 2.120 seconds instead of ten. The warning is still there, and the container is still killed:level=warning msg="StopSignal SIGTERM failed to stop container impatient in 2 seconds, resorting to SIGKILL"Useful for a test suite that starts and stops containers constantly. It is not a fix - you have shortened the grace period, not made anything graceful, and on a real workload you have made an ungraceful shutdown *more* likely by giving a process that does handle SIGTERM less time to finish.
The order to try, then: handle the signal if the code is yours;
--initif it is not;--stop-timeoutonly when you know nothing needs the time. And ifpodman stopreliably takes exactly the timeout, that is not a slow container - it is a container that is not listening.bash Example session podman run -d --name impatient --stop-timeout 2 docker.io/library/alpine sleep 300189fe7131608daee4da22177bcb06239d781469624ff18d0c8830e11af5ab598time podman stop impatienttime="2026-08-22T11:32:06Z" level=warning msg="StopSignal SIGTERM failed to stop container impatient in 2 seconds, resorting to SIGKILL"impatient real 0m2.120suser 0m0.032ssys 0m0.030spodman rm nosig withinit trapper impatientimpatienttrappernosigwithinitExpected resultThe same warning at two seconds instead of ten.
Success conditionYou can tell a container that shut down from one that was killed quickly.
Troubleshooting
podman stopalways takes exactly the timeout, on every container.Why: Nothing is handling SIGTERM. The timeout is not a delay, it is a deadline being reached.
Fix:
podman exec <c> ps -eo pid,comm- if your process is PID 1 and is not a real init, that is the cause. Add--initor handle the signal.The app handles SIGTERM in testing but not in a container.
Why: A shell is PID 1 and the app is its child, so the shell receives the signal and discards it.
Fix:
execthe app so it replaces the shell, or use the exec formCMD ["myapp"]in the Containerfile.Zombie processes accumulate inside a long-running container.
Why: PID 1 is not reaping orphans, which is the other half of an init's job.
Fix:
--init.podman exec <c> ps -eo pid,stat,commshowsZstate processes if this is happening.The container needs longer than ten seconds to drain cleanly.
Why: The default timeout is shorter than the work.
Fix:Raise it:
--stop-timeout 60, orpodman stop --time 60for one invocation. Also settable per image withSTOPSIGNALand honoured bypodman kube playthroughterminationGracePeriodSeconds.