How to Gracefully Shut Down Docker Containers Using Signals and ENTRYPOINT
This article explains Linux signal fundamentals, the role of Dockerfile ENTRYPOINT and CMD directives, and demonstrates with Go and shell examples how using the exec form enables containers to receive termination signals for clean shutdowns instead of being force‑killed.
1 Signals
Signals are a notification mechanism for processes in Linux, sometimes called software interrupts.
Linux defines standard signals numbered 1–31, which can be listed with
# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT
4) SIGILL 5) SIGTRAP 6) SIGABRT
7) SIGBUS 8) SIGFPE 9) SIGKILL
10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM
...Common signals include:
SIGHUP – sent when a terminal disconnects; daemons often reload configuration on this signal.
SIGINT – generated by Ctrl‑C; default action terminates the process.
SIGQUIT – generated by Ctrl‑\; terminates the process and creates a core dump.
SIGKILL – cannot be caught or ignored; always terminates the process.
SIGTERM – the standard termination signal used by docker stop ; well‑designed programs handle it to clean up resources before exiting.
SIGTSTP – job‑control stop signal generated by Ctrl‑Z.
Note that Control‑D does not send a signal; it signals EOF on stdin.
Programs can catch signals and run handler functions:
The above knowledge mainly comes from "The Linux/UNIX System Programming Handbook", chapters 20‑22.
2 ENTRYPOINT, CMD
Both directives specify the program that runs when a container starts.
CMD has three formats:
CMD ["executable","param1","param2"] (exec format, recommended)
CMD ["param1","param2"] (as arguments to ENTRYPOINT)
CMD command param1 param2 (shell format, defaults to /bin/sh -c)
ENTRYPOINT also has two formats:
ENTRYPOINT ["executable","param1","param2"] (exec format, recommended)
ENTRYPOINT command param1 param2 (shell format)
Using the exec format is preferred because the shell format runs the command via /bin/sh -c, which does not forward signals to the program, preventing graceful shutdown when docker stop sends SIGTERM.
➜ ~ docker stop --help
Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
Stop one or more running containers
Options:
--help Print usage
-t, --time int Seconds to wait for stop before killing it (default 10) docker stopsends SIGTERM by default and, after the timeout, SIGKILL.
➜ ~ docker kill --help
Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...]
Kill one or more running containers
Options:
--help Print usage
-s, --signal string Signal to send to the container (default "KILL")3 Examples
3.1 Example 1
A simple Go signal handler:
➜ ~ cat signals.go
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
sigs := make(chan os.Signal, 1)
done := make(chan bool, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigs
fmt.Println()
fmt.Println(sig)
done <- true
}()
fmt.Println("awaiting signal")
<-done
fmt.Println("exiting")
}Dockerfile (exec CMD):
FROM busybox
COPY signals /signals
CMD ["/signals"] # exec formatRunning the container and stopping it:
➜ ~ docker run -it --rm --name signals signals
awaiting signal
terminated
exiting ➜ ~ time docker stop signals
signals
docker stop signals 0.01s user 0.02s system 4% cpu 0.732 totalGraceful shutdown occurs in ~0.73 s.
Changing CMD to shell format:
FROM busybox
COPY signals /signals
CMD /signals # shell format ➜ ~ docker run -it --rm --name signals signals
awaiting signal ➜ ~ time docker stop signals
signals
docker stop signals 0.01s user 0.01s system 0% cpu 10.719 totalWithout signal forwarding, the container is force‑killed after the default 10 s timeout.
3.2 Example 2
When the program is started via a shell script, signals still need to be forwarded. Dockerfile:
FROM busybox
COPY signals /signals
COPY start.sh /start.sh # add shell script
CMD ["/start.sh"] #!/bin/sh
/signalsRunning this yields the same problem as the shell CMD case. Adding exec in the script fixes it:
#!/bin/sh
exec /signals # forward signals ➜ ~ docker run -it --rm --name signals signals
awaiting signal
terminated
exiting ➜ ~ time docker stop signals
signals
docker stop signals 0.02s user 0.02s system 4% cpu 0.744 totalConclusion: to achieve graceful container shutdown, always use the exec form for ENTRYPOINT/CMD, and if a shell script is involved, prepend exec so that signals reach the actual process.
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.
