Q: During rolling deployments in Kubernetes and Docker Swarm, users experience 502 Bad Gateway errors and database transactions are abruptly severed mid-flight. Logs reveal that containers take exactly 10 seconds to terminate during deployment, indicating that the applications never received `SIGTERM` and were forcibly killed by `SIGKILL` (exit code 137). You must audit the container entrypoint definitions, resolve signal swallowing in wrapper shell scripts, and implement connection draining.
Implement bulletproof graceful termination in containerized applications. Diagnose shell-form vs exec-form ENTRYPOINT signal masking, bash trap handlers, and HTTP connection draining before SIGKILL.
Want to master this scenario in a live sandbox? KodeKloud's Docker Certified Associate (DCA) Hands-On Lab Course covers this exact problem with hands-on terminal drills.
🛠️ Production Runbook & Step-by-Step Resolution
Differentiate Dockerfile Shell Form vs Exec Form
Understand syntax consequences: Shell form (`ENTRYPOINT command param`) wraps the command in `/bin/sh -c`, making `/bin/sh` PID 1. Standard shells do not forward signals to child processes. Exec form (`ENTRYPOINT ["command", "param"]`) executes the binary directly as PID 1, receiving signals directly.
# Shell Form (ANTI-PATTERN - Signals Swallowed!):
ENTRYPOINT ./start-server.sh
# Linux executes: /bin/sh -c ./start-server.sh (PID 1 is /bin/sh, ignores SIGTERM!)
# Exec Form (CORRECT):
ENTRYPOINT ["./start-server.sh"]
# Linux executes start-server.sh directly as PID 1
Implement Signal Forwarding Traps in Wrapper Shell Scripts
If an entrypoint must run as a shell script to perform pre-flight checks, implement a Bash `trap` handler that catches `SIGTERM` and `SIGINT`, forwards them to the background application PID, and waits for graceful termination.
#!/usr/bin/env bash
set -e
# Pre-flight tasks
echo "Running pre-flight database migrations..."
/app/migrate
# Start application in background and capture PID
/app/web-server &
APP_PID=$!
# Trap SIGTERM and SIGINT, forwarding to background process
_term() {
echo "Caught SIGTERM signal! Forwarding to web-server (PID: $APP_PID)..."
kill -TERM "$APP_PID" 2>/dev/null
wait "$APP_PID"
echo "Application successfully terminated."
exit 0
}
trap _term SIGTERM SIGINT
# Wait for process to finish
wait "$APP_PID"
Alternative: Replace the Shell Script with Exec
The cleanest pattern for shell wrapper scripts is using `exec` for the final application invocation. `exec` replaces the shell process with the application binary while preserving PID 1.
#!/bin/sh
set -e
# Pre-startup checks
export DATABASE_URL=$(cat /run/secrets/db_url)
# Exec replaces the shell process entirely with the application binary
exec /app/web-server --config /etc/app.yaml
Test Graceful Shutdown and Verify Exit Code 0
Send `SIGTERM` to the running container using `docker stop` and verify in logs that the application executes its cleanup routine and exits with status 0 before the 10-second timeout expires.
# Start container and monitor logs
docker run -d --name grace-test my-app:latest
docker logs -f grace-test &
# Issue stop command and measure termination duration
time docker stop grace-test
# Output confirms exit within 1.2 seconds with exit code 0
- W
- e
- e
- l
- i
- m
- i
- n
- a
- t
- e
- d
- 5
- 0
- 2
- e
- r
- r
- o
- r
- s
- d
- u
- r
- i
- n
- g
- r
- o
- l
- l
- i
- n
- g
- d
- e
- p
- l
- o
- y
- m
- e
- n
- t
- s
- b
- y
- r
- e
- s
- o
- l
- v
- i
- n
- g
- s
- i
- g
- n
- a
- l
- m
- a
- s
- k
- i
- n
- g
- i
- n
- o
- u
- r
- D
- o
- c
- k
- e
- r
- c
- o
- n
- t
- a
- i
- n
- e
- r
- s
- .
- B
- y
- r
- e
- p
- l
- a
- c
- i
- n
- g
- s
- h
- e
- l
- l
- -
- f
- o
- r
- m
- e
- n
- t
- r
- y
- p
- o
- i
- n
- t
- s
- w
- i
- t
- h
- e
- x
- e
- c
- -
- f
- o
- r
- m
- s
- y
- n
- t
- a
- x
- a
- n
- d
- u
- s
- i
- n
- g
- `
- e
- x
- e
- c
- `
- i
- n
- o
- u
- r
- s
- t
- a
- r
- t
- u
- p
- s
- c
- r
- i
- p
- t
- s
- ,
- `
- S
- I
- G
- T
- E
- R
- M
- `
- s
- i
- g
- n
- a
- l
- s
- n
- o
- w
- r
- e
- a
- c
- h
- a
- p
- p
- l
- i
- c
- a
- t
- i
- o
- n
- r
- u
- n
- t
- i
- m
- e
- s
- d
- i
- r
- e
- c
- t
- l
- y
- ,
- e
- n
- a
- b
- l
- i
- n
- g
- t
- h
- e
- m
- t
- o
- d
- r
- a
- i
- n
- d
- a
- t
- a
- b
- a
- s
- e
- p
- o
- o
- l
- s
- a
- n
- d
- f
- i
- n
- i
- s
- h
- a
- c
- t
- i
- v
- e
- H
- T
- T
- P
- r
- e
- q
- u
- e
- s
- t
- s
- i
- n
- s
- e
- c
- o
- n
- d
- s
- b
- e
- f
- o
- r
- e
- e
- x
- i
- t
- i
- n
- g
- c
- l
- e
- a
- n
- l
- y
- .