docker stopStop a container gracefully
docker stop asks a container's main process to shut down with a signal (SIGTERM by default), waits up to 10 seconds, then kills it with SIGKILL. Whether your app actually gets that signal, and uses the time to finish requests, depends on how the image starts it.
docker stop [-t SECONDS] [-s SIGNAL] CONTAINER [CONTAINER...]You need to take the web container down for maintenance without dropping in-flight requests.
docker stopSend the stop signal to PID 1 of each container, then SIGKILL after the timeout.
dockerd looks up the container's stop signal (the image's STOPSIGNAL, else SIGTERM; nginx uses SIGQUIT, postgres SIGINT) and has containerd deliver it to PID 1. Then it waits for the grace period. If PID 1 hasn't exited by then, it sends SIGKILL, which can't be caught, and the container ends with exit code 137. The catch: inside its PID namespace your process is PID 1, and the kernel doesn't apply default signal actions to PID 1. SIGTERM only works if the program installs a handler. With a shell-form CMD, /bin/sh is PID 1 on Debian-based images and never forwards the signal; on Alpine the shell execs the app, which then must handle SIGTERM itself. Either way, a stop without a handler takes the full 10 seconds and ends in a hard kill. Exec-form CMD plus a handler, exec in entrypoint scripts, or --init (tini as PID 1, forwarding signals) fix it. A stopped container keeps its filesystem and logs until docker rm.
-t, --time SECONDSGrace period before SIGKILL (default 10)-s, --signal SIGNALSend this signal instead of the image's STOPSIGNALdocker kill CONTAINERSIGKILL immediately, no grace perioddocker kill -s HUP CONTAINERSend any signal (for example reload) without stoppingdocker run --stop-timeout NSet a per-container default grace perioddocker run --initRun tini as PID 1 so signals reach your app and zombies are reapeddocker start / restartStart a stopped container again / stop then startCMD node server.js (shell form) or an entrypoint script that runs the app without execsh becomes PID 1, never forwards SIGTERM, and every stop ends in SIGKILL after 10 s: dropped requests and half-done jobs.
CMD ["node", "server.js"] and exec "$@" at the end of entrypoint scripts, or docker run --initdocker kill as the normal way to stop thingsSIGKILL gives the app no chance to flush buffers, finish requests or close DB connections cleanly.
docker stop (with -t long enough), and kill only when stop doesn't workAssuming docker stop deletes the containerIt only stops it. Stopped containers keep their disk, names and logs until removed.
docker rm after stopping, or docker run --rm for throwaway containersTry these on a Linux machine of your own. Each task has a hint and a solution.
You can practise signals in the sandbox: start 'sleep 300 &', send it SIGTERM with kill, and print its exit status with wait.
Write a shell script ~/app/entrypoint.sh that prints 'starting' and then replaces itself with 'node src/server.js', so the app becomes PID 1 and gets SIGTERM.
Write the docker command that gives the container db up to 90 seconds to stop before it's killed.
docker stopStop a container gracefully
docker stop asks a container's main process to shut down with a signal (SIGTERM by default), waits up to 10 seconds, then kills it with SIGKILL. Whether your app actually gets that signal, and uses the time to finish requests, depends on how the image starts it.
docker stop [-t SECONDS] [-s SIGNAL] CONTAINER [CONTAINER...]You need to take the web container down for maintenance without dropping in-flight requests.
docker stopSend the stop signal to PID 1 of each container, then SIGKILL after the timeout.
dockerd looks up the container's stop signal (the image's STOPSIGNAL, else SIGTERM; nginx uses SIGQUIT, postgres SIGINT) and has containerd deliver it to PID 1. Then it waits for the grace period. If PID 1 hasn't exited by then, it sends SIGKILL, which can't be caught, and the container ends with exit code 137. The catch: inside its PID namespace your process is PID 1, and the kernel doesn't apply default signal actions to PID 1. SIGTERM only works if the program installs a handler. With a shell-form CMD, /bin/sh is PID 1 on Debian-based images and never forwards the signal; on Alpine the shell execs the app, which then must handle SIGTERM itself. Either way, a stop without a handler takes the full 10 seconds and ends in a hard kill. Exec-form CMD plus a handler, exec in entrypoint scripts, or --init (tini as PID 1, forwarding signals) fix it. A stopped container keeps its filesystem and logs until docker rm.
-t, --time SECONDSGrace period before SIGKILL (default 10)-s, --signal SIGNALSend this signal instead of the image's STOPSIGNALdocker kill CONTAINERSIGKILL immediately, no grace perioddocker kill -s HUP CONTAINERSend any signal (for example reload) without stoppingdocker run --stop-timeout NSet a per-container default grace perioddocker run --initRun tini as PID 1 so signals reach your app and zombies are reapeddocker start / restartStart a stopped container again / stop then startCMD node server.js (shell form) or an entrypoint script that runs the app without execsh becomes PID 1, never forwards SIGTERM, and every stop ends in SIGKILL after 10 s: dropped requests and half-done jobs.
CMD ["node", "server.js"] and exec "$@" at the end of entrypoint scripts, or docker run --initdocker kill as the normal way to stop thingsSIGKILL gives the app no chance to flush buffers, finish requests or close DB connections cleanly.
docker stop (with -t long enough), and kill only when stop doesn't workAssuming docker stop deletes the containerIt only stops it. Stopped containers keep their disk, names and logs until removed.
docker rm after stopping, or docker run --rm for throwaway containersTry these on a Linux machine of your own. Each task has a hint and a solution.
You can practise signals in the sandbox: start 'sleep 300 &', send it SIGTERM with kill, and print its exit status with wait.
Write a shell script ~/app/entrypoint.sh that prints 'starting' and then replaces itself with 'node src/server.js', so the app becomes PID 1 and gets SIGTERM.
Write the docker command that gives the container db up to 90 seconds to stop before it's killed.