Cloud Native 12 min read

How to Gracefully Shut Down Docker Containers Using Signals and ENTRYPOINT

This article explains Linux signals, the differences between Dockerfile CMD and ENTRYPOINT formats, and demonstrates with Go and shell examples how using the exec form enables containers to receive termination signals for a clean shutdown.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
How to Gracefully Shut Down Docker Containers Using Signals and ENTRYPOINT

1 Signal

Signals are a notification mechanism for processes, 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 ...
SIGHUP

is sent when a terminal disconnects; many daemons reload configuration on receiving it. SIGINT is generated by Ctrl‑C and terminates the process by default. SIGQUIT is generated by Ctrl‑\ , terminates the process and creates a core dump. SIGKILL cannot be caught or ignored and always kills the process. SIGTERM is the default signal sent by kill, killall or pkill; well‑designed applications handle it to clean up resources before exiting. SIGTSTP stops a job when the user types Ctrl‑Z .

Note that Ctrl‑D does not send a signal; it signals EOF and closes standard input.

Programs can install signal handlers to execute custom logic when a signal arrives.

Most of this knowledge comes from the "Linux/UNIX System Programming" manual, chapters 20‑22.

2 ENTRYPOINT and CMD

Both directives specify the program that runs when a container starts. CMD has three formats: CMD ["executable","param1","param2"] (exec form, recommended) CMD ["param1","param2"] (as arguments to ENTRYPOINT) CMD command param1 param2 (shell form, runs via /bin/sh -c) ENTRYPOINT has two formats: ENTRYPOINT ["executable","param1","param2"] (exec form, preferred) ENTRYPOINT command param1 param2 (shell form)

When the shell form is used, the program runs as a child of /bin/sh -c, which does not forward signals to the child. Consequently, docker stop sends SIGTERM but the program never receives it, and Docker falls back to SIGKILL after the timeout.

docker stop --help
Usage:  docker stop [OPTIONS] CONTAINER [CONTAINER...]
Options:
      --help       Print usage
  -t, --time int   Seconds to wait for stop before killing it (default 10)

By default, docker stop sends SIGTERM and, after 10 seconds, SIGKILL if the container is still running. The timeout can be changed with -t.

docker kill --help
Usage:  docker kill [OPTIONS] CONTAINER [CONTAINER...]
Options:
      --help            Print usage
  -s, --signal string   Signal to send to the container (default "KILL")

Therefore, using the exec form for CMD or ENTRYPOINT ensures the container’s main process receives termination signals and can shut down gracefully.

3 Examples

3.1 Example 1 – Go signal handler

Go program ( 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 form):

FROM busybox
COPY signals /signals
CMD ["/signals"]

Build and run the image, then stop it:

docker build -t signals .

docker run -it --rm --name signals signals
awaiting signal

# In another terminal
time docker stop signals
signals
docker stop signals  0.01s user 0.02s system 4% cpu 0.732 total

The program receives SIGTERM, prints the signal, and exits in ~0.73 s, demonstrating a graceful shutdown.

When the shell form is used ( CMD /signals), the program does not receive the signal and Docker kills it after the default 10 s timeout:

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 total

Conclusion: use the exec form for CMD to enable graceful termination.

3.2 Example 2 – Shell script wrapper

When the container’s command is a shell script, signals are not forwarded unless the script uses exec to replace the shell with the target program.

Dockerfile:

FROM busybox
COPY signals /signals
COPY start.sh /start.sh
CMD ["/start.sh"]
start.sh

(initial version):

#!/bin/sh
/signals

Running this image with docker stop results in a forced kill:

docker run -it --rm --name signals signals
awaiting signal

time docker stop signals
signals
docker stop signals  0.01s user 0.02s system 0% cpu 10.765 total

Fix by adding exec in the script:

#!/bin/sh
exec /signals

Rebuild and run:

docker build -t 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 total

Now the program receives SIGTERM and exits cleanly. If the script is executed via the shell form of CMD, even adding exec inside the script will not help, and the container will still be killed forcefully.

In summary, to achieve graceful shutdown of Docker containers, always use the exec form for CMD or ENTRYPOINT, and ensure any wrapper scripts also invoke exec to pass signals to the actual process.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DockerGoGraceful ShutdowncmdsignalsENTRYPOINT
MaGe Linux Operations
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.