What's the difference between stopping and killing a container?
Quick Answer
docker stop sends SIGTERM first, giving the container's main process a grace period (10 seconds by default) to shut down cleanly, and only sends SIGKILL if it hasn't exited by the end of that period. docker kill sends SIGKILL, or another specified signal, immediately, with no grace period, forcibly terminating the process right away. stop is the correct default for anything that should get a chance to clean up, like closing database connections or finishing in-flight requests. kill is for when you need the container gone immediately and don't care about a graceful shutdown.
Detailed Answer
docker stop — graceful, with a timeout
docker stop my-container
- Sends
SIGTERMto the container's main process (PID 1 inside its namespace). - Waits up to a grace period (10 seconds by default) for the process to exit on its own.
- If it hasn't exited by then, Docker escalates and sends
SIGKILL, forcibly terminating it immediately, with no further waiting.
docker stop -t 30 my-container # give it up to 30 seconds before force-killing
The -t/--time flag adjusts this grace period. Worth increasing for applications that need more time to finish in-flight work cleanly — draining active connections, completing a batch operation — before shutting down.
docker kill — immediate, no grace period
docker kill my-container # sends SIGKILL immediately, by default
docker kill -s SIGINT my-container # or, send a different specific signal instead
There's no grace period at all. The specified signal, SIGKILL by default, is sent right away. If it's SIGKILL specifically, the process can't catch or ignore it — SIGKILL isn't interceptable, by design, in the Linux kernel. The process is terminated immediately and unconditionally.
Why the SIGTERM grace period matters
// A well-behaved application handles SIGTERM to shut down cleanly
process.on('SIGTERM', () => {
console.log('Received SIGTERM, finishing in-flight requests...');
server.close(() => {
db.disconnect();
process.exit(0);
});
});
A well-designed application listens for SIGTERM and uses that grace period to stop accepting new requests, finish requests already in progress, close database connections cleanly, and flush any buffered writes. None of that can happen if the process is killed outright with SIGKILL first. This is exactly why docker stop, not docker kill, is the correct default for routine container shutdowns, restarts, and deployments. Abruptly SIGKILLing a container mid-request can corrupt in-progress writes, leave connections in a bad state, or drop requests that were nearly complete.
The exec-form vs. shell-form connection
Using shell form for CMD/ENTRYPOINT — CMD node server.js instead of CMD ["node", "server.js"] — makes a shell process PID 1 instead of the application itself. That shell often doesn't correctly forward SIGTERM to the actual application process underneath it. This is exactly why a container can appear to "ignore" docker stop and always take the full grace period before being force-killed: the SIGTERM sent by docker stop may never actually reach the application, even though the application would have handled it correctly if it had received it directly as PID 1.
When docker kill is the right choice
- A container that's hung or unresponsive and clearly isn't going to shut down gracefully no matter how long you wait, and you need it gone immediately.
- Local development/testing, where a fast iteration loop matters more than clean shutdown semantics.
- Debugging scenarios where you specifically want to simulate an abrupt, ungraceful termination — for example, testing how a dependent system reacts to a sudden connection drop.
If you find yourself reaching for docker kill regularly just because docker stop "never works fast enough," that's usually a sign the container's CMD/ENTRYPOINT isn't actually receiving and handling SIGTERM correctly — not a reason to make kill the new default.