Safeguard
Developer Tools•

Why does my container ignore docker stop? Exec form and signals

A shell form CMD makes a shell PID 1, so your app may never see SIGTERM. Use exec form or the exec builtin so containers shut down cleanly and on time.

Safeguard Security Team
3 min read

A container ignores docker stop when its main process never receives the SIGTERM signal. This usually happens with shell form CMD or ENTRYPOINT, where a shell runs as PID 1 and your app is only its child. Switch to exec form, or call exec in your start script.

What actually happens on docker stop

The Dockerfile reference says docker stop sends a signal to end the container, and the default is SIGTERM. You can change it with the STOPSIGNAL instruction or per container at run time. Whatever process runs as PID 1 inside the container is the one that gets it.

Now look at how you wrote the start command. Shell form looks like this:

CMD node server.js

Docker runs that under a shell. The reference states that in shell form your process is a child of the shell, so it is not PID 1 and does not receive signals such as SIGTERM from docker stop. The shell may not forward the signal, so the app keeps running until the engine gives up and forces it to end.

Exec form fixes it

Exec form is a JSON array and runs the program directly, with no shell in between.

CMD ["node", "server.js"]

Docker's best practices page says CMD should almost always be used in this form. The reference prefers it for ENTRYPOINT too, and for both when they work together. A side effect: because no shell runs, environment variable expansion in the command does not happen. If you need it, read the variables inside your program or use a small start script.

When you need a start script

Many images run a script to render config, then start the app. The best practices page recommends ending such a script with the exec builtin so the final application becomes PID 1 and receives Unix signals.

#!/bin/sh
set -e
render_config
exec node server.js

Without exec, the script stays PID 1 and the app is again a child.

Why this is a security topic

Slow or forced shutdowns look like an operations nuisance, but they matter for safety. Rolling out a patched image depends on old containers stopping promptly. Graceful shutdown also lets apps flush logs and close connections, which keeps audit trails complete. And a process that cannot be stopped cleanly tends to get stopped with force, which can drop in flight work.

Checklist

CheckGood sign
CMD and ENTRYPOINT in JSON array formYes
Start scripts finish with execYes
STOPSIGNAL matches what your app handlesYes
App handles SIGTERM in codeYes

To test, run the container, call docker stop, and watch how long it takes. Then check your logs for a clean shutdown message.

Quick check

Is shell form CMD always wrong?

Not always, but it is a common cause of missed signals. Prefer exec form, or use the exec builtin in a script.

Does Ctrl+C use the STOPSIGNAL setting?

No. The reference says STOPSIGNAL does not affect Ctrl+C, which sends SIGINT directly to the process.

Safeguard

Safeguard does SBOM and dependency scanning, and its policies and gates can run in CI so a bad image does not reach production. You can try a free scan before deciding anything.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.