How to Gracefully Stop Docker Containers: Signals, Exit Codes, and Go Example
This guide explains how Docker containers can be gracefully stopped by handling Linux signals such as SIGTERM, details common exit codes, demonstrates a Go program that captures these signals, and provides best‑practice Dockerfile configurations to ensure proper shutdown behavior.
1. Overview
Any application wants to receive a stop notification before termination so it can release resources, close connections, and finish pending work. For example, a web service should finish all in‑flight HTTP requests, and a file‑writing process should flush data to disk before the container stops.
2. Common Linux Signals
Signals are a form of inter‑process communication. A signal is a message from the kernel indicating an event. Processes register handlers for signals they care about.
Programs typically handle SIGTERM to exit gracefully; SIGKILL terminates a process abruptly.
Daemons often use SIGHUP for hot‑reloading configuration files.
The kill -l command lists supported signals. Signals 1‑31 are traditional (non‑real‑time); 32‑63 are reliable (real‑time) signals.
SIGHUP (1)
Sent when a terminal disconnects; also used for hot‑reloading configs. Services like wget, Docker, Nginx, and LVS register SIGHUP to reload configuration without stopping.
SIGINT (2)
Interrupt signal generated by Ctrl+C, notifying the foreground process group to terminate.
SIGQUIT (3)
Similar to SIGINT but triggered by Ctrl+\. Nginx uses it for graceful shutdown.
SIGKILL (9)
Immediately terminates a program. This signal cannot be blocked, handled, or ignored.
SIGTERM (15)
Terminate signal (request to exit). Unlike SIGKILL, it can be caught and handled, allowing graceful shutdown. The kill command sends SIGTERM by default.
SIGCHLD (17)
Sent to a parent when a child process exits. Nginx uses it for master‑worker communication.
3. Common Docker Container Exit Codes
Exit Code 1
Program error or missing file referenced in Dockerfile (e.g., wrong entrypoint).
Examples: division by zero, null reference, or crash.
Exit Code 137
Indicates the container received SIGKILL (kill -9).
Triggered by docker kill or OOMKilled when memory limits are too low.
Exit Code 139
Indicates the container received SIGSEGV (invalid memory access, kill -11).
Usually caused by buggy code or a faulty base image.
Exit Code 143
Indicates the container received SIGTERM (kill -15), typically from docker stop.
Sometimes docker stop falls back to SIGKILL, resulting in 137 if the program cannot handle SIGTERM within the timeout.
Other Exit Codes
126 – Permission problem or non‑executable command.
127 – Command not found (often a typo in a shell script).
1 or 255 – Custom exit codes from programs (e.g., exit(1) or exit(-1) which maps to 255).
For processes terminated by a signal, the OS adds 128 to the signal number to form the exit status (e.g., SIGKILL 9 → 137, SIGTERM 15 → 143). This convention helps distinguish normal exits (0‑127) from signal‑induced exits (128‑255) in container environments.
4. Docker Container Signal Support
Docker provides extensive support for Linux signals.
4.1 docker stop Signal Support
When docker stop is executed, Docker sends SIGTERM to the container’s PID 1 and waits (default 10 seconds) before sending SIGKILL. The timeout can be changed with --time (or -t).
docker stop --help
Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
Options:
-t, --time int Seconds to wait for stop before killing it (default 10)4.2 docker kill Signal Support
docker killsends SIGKILL by default, but you can specify any signal with --signal (or -s).
docker kill --signal=SIGINT container_name4.3 docker rm Signal Support
docker rm -fforces removal of a running container by first sending SIGKILL, then deleting the container.
4.4 Docker Daemon Signal Support
The Docker daemon (dockerd) reloads its configuration when it receives SIGHUP. You can trigger this with:
kill -SIGHUP $(pidof dockerd)
# or
systemctl reload dockerAfter reloading, the daemon logs “Got signal to reload configuration”.
Note: systemctl reload docker reloads the daemon without restarting containers; systemctl restart docker stops and restarts the daemon, causing all containers to restart.
5. Graceful Shutdown Example for a Service
Below is a simple Go program that registers handlers for SIGTERM and SIGINT, prints a message when a signal is received, and exits.
// main.go
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
fmt.Println("Program started…")
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM)
signal.Notify(ch, syscall.SIGINT)
s := <-ch
switch {
case s == syscall.SIGINT:
fmt.Println("SIGINT received!")
// Do something…
case s == syscall.SIGTERM:
fmt.Println("SIGTERM received!")
// Do something…
}
fmt.Println("Exiting…")
}Build the binary for Linux:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o gracefulRun the binary in a container:
FROM alpine:latest
ADD graceful /graceful
CMD ["/graceful"]Test the program:
# Foreground, then Ctrl+C
./graceful
Program started…
^CSIGINT received!
Exiting…
# Background, then kill
./graceful &
kill <pid>
Program started…
SIGTERM received!
Exiting…Build the Docker image:
docker build -t graceful-golang-case:1.0.0 .Run the container:
docker run -d --name graceful graceful-golang-case:1.0.0Check logs to confirm the program started:
docker logs graceful
Program started…Stop the container with a custom timeout to give the program time to clean up:
docker stop --time=120 gracefulLogs show the program handled SIGTERM and exited cleanly.
6. Summary
To achieve graceful shutdown of Docker containers, ensure your application registers and handles the SIGTERM signal. Use docker stop (not docker kill or docker rm -f) so the container receives SIGTERM and has a chance to finish work. In Dockerfiles, prefer the exec form of CMD or ENTRYPOINT to guarantee that signals are delivered directly to your application process.
Q&A
Q1: How can I verify that my program’s SIGTERM handler executed?
A: Check the container’s logs for the expected output.
References:
Gracefully Stopping Docker Containers
Best Practices for Pod Pre‑Stop
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
