Exit code 143 indicates that a Docker container received a SIGTERM signal and terminated gracefully. This is typically a normal shutdown behavior when stopping containers with docker stop, during orchestrator scaling, or when manually terminating processes.
Exit code 143 is calculated as 128 + 15, where 15 is the signal number for SIGTERM (the standard Unix termination signal). When a container exits with code 143, it means the main process received a SIGTERM signal and shut down accordingly. This is generally considered a healthy shutdown - unlike exit code 137 (SIGKILL), which indicates a forced termination, exit code 143 shows that the container had the opportunity to perform cleanup operations before exiting. SIGTERM is a 'polite' termination request that gives processes a chance to gracefully shut down - closing database connections, completing in-flight requests, flushing logs, and releasing resources. When you run `docker stop`, Docker sends SIGTERM to the container's main process (PID 1) and waits for a configurable grace period (default 10 seconds) before escalating to SIGKILL if the process hasn't exited. In most cases, exit code 143 is not an error but expected behavior indicating your container properly handled the shutdown signal.
First, determine whether the SIGTERM was intentional. Exit code 143 after these operations is normal:
# These commands send SIGTERM and result in exit 143
docker stop <container>
docker-compose down
kubectl delete pod <pod>
kubectl rollout restart deployment/<name>Check if the exit coincides with deployments, scaling events, or manual intervention:
# Check container exit details
docker inspect <container-id> --format='{{.State.ExitCode}} - {{.State.FinishedAt}}'
# For Kubernetes, check events
kubectl describe pod <pod-name> | grep -A 10 EventsIf exit code 143 appears when you didn't expect a shutdown, continue investigating.
Review the container logs to understand what happened before termination:
# View recent logs including shutdown messages
docker logs --tail 100 <container-id>
# For Kubernetes, check previous container logs
kubectl logs <pod-name> --previousLook for:
- Graceful shutdown messages (good sign)
- Error messages before shutdown
- Connection termination logs
- Resource cleanup confirmations
A healthy shutdown typically shows messages like 'Received SIGTERM, shutting down...' followed by cleanup logs.
If your application isn't handling SIGTERM, it may exit abruptly without cleanup. Implement signal handling:
Node.js:
process.on('SIGTERM', () => {
console.log('Received SIGTERM, shutting down gracefully...');
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});Python:
import signal
import sys
def handle_sigterm(signum, frame):
print('Received SIGTERM, cleaning up...')
# Cleanup code here
sys.exit(0)
signal.signal(signal.SIGTERM, handle_sigterm)Go:
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGTERM)
<-quit
// Graceful shutdown logicContainers that run applications as PID 1 may not handle signals correctly by default. Use an init system:
Option 1: Docker's built-in init (recommended)
docker run --init <image>Or in docker-compose.yml:
services:
app:
init: true
image: myappOption 2: Use tini in Dockerfile
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["./myapp"]Option 3: Use exec in shell entrypoints
#!/bin/sh
# setup commands...
exec ./myapp # Replace shell with app, so app receives signalsIf your application needs more time to shut down gracefully, increase the timeout:
Docker:
# Give container 60 seconds to shut down
docker stop --time=60 <container>Docker Compose:
services:
app:
stop_grace_period: 60sKubernetes:
spec:
terminationGracePeriodSeconds: 60
containers:
- name: app
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 5"]The default is 10 seconds in Docker and 30 seconds in Kubernetes.
The shell form of CMD/ENTRYPOINT wraps your command in /bin/sh -c, which doesn't forward signals:
# BAD: Shell form - signals go to shell, not your app
CMD python app.py
# GOOD: Exec form - signals go directly to your app
CMD ["python", "app.py"]Same applies to ENTRYPOINT:
# BAD: Shell form
ENTRYPOINT ./start.sh
# GOOD: Exec form
ENTRYPOINT ["./start.sh"]Always use the JSON array (exec) form unless you specifically need shell features.
If containers receive unexpected SIGTERM signals in Kubernetes, check for:
OOM evictions (memory pressure):
kubectl describe pod <pod-name> | grep -i oom
kubectl top pod <pod-name>Failed health checks:
kubectl describe pod <pod-name> | grep -A 5 'Liveness\|Readiness'Node issues:
kubectl describe node <node-name> | grep -A 10 ConditionsResource quota exceeded:
kubectl describe quota -n <namespace>Check cluster events for termination reasons:
kubectl get events --sort-by='.lastTimestamp' | grep -i terminExit code 143 differs significantly from 137 (SIGKILL): while 143 indicates graceful termination, 137 means the process was forcefully killed, often due to timeout or OOM. In production, seeing 143 is generally positive - it means your application responded to the shutdown signal. However, if the shutdown takes too long (approaching the grace period), the orchestrator will escalate to SIGKILL.
Some applications use custom stop signals. For example, nginx and php-fpm use SIGQUIT for graceful shutdown instead of SIGTERM. You can configure this in your Dockerfile with STOPSIGNAL SIGQUIT or via docker run with --stop-signal=SIGQUIT.
In Kubernetes, the termination sequence is: preStop hook (if defined) -> SIGTERM -> wait terminationGracePeriodSeconds -> SIGKILL. Understanding this sequence helps debug shutdown issues. For long-running connections (WebSockets, database connections), implement connection draining in your preStop hook to allow in-flight requests to complete.
When running multiple processes in a container (not recommended but sometimes necessary), only PID 1 receives signals. Use a process manager like supervisord configured to forward signals, or redesign with multiple containers.
dockerfile parse error line 5: unknown instruction: RRUN
How to fix 'unknown instruction' Dockerfile parse error in Docker
Error response from daemon: manifest for nginx:nonexistent not found: manifest unknown: manifest unknown
How to fix 'manifest for image:tag not found' in Docker
Error response from daemon: invalid reference format: repository name must be lowercase
How to fix 'repository name must be lowercase' in Docker
Error response from daemon: No such image
How to fix 'No such image' in Docker
Error response from daemon: Container is not running
How to fix 'Container is not running' when using docker exec