warning docker

Docker Exit Code 143 - Graceful Termination (SIGTERM)

Understanding Docker exit code 143 - the container received SIGTERM and terminated gracefully, typically from docker stop.

What It Means

Docker exit code 143 (128 + 15) indicates that the container’s main process received SIGTERM and was terminated. This is the expected behavior when running docker stop, Kubernetes pod termination, or Docker Compose bringing down services.

Exit code 143 means the process did not catch SIGTERM and perform its own exit — if it had, it would typically exit with code 0. Seeing 143 means the default signal handler terminated the process.

Common Causes

  • docker stop was used to stop the container
  • Kubernetes is terminating the pod (rolling update, scale down)
  • docker compose down or docker compose stop
  • Systemd stopping the Docker service
  • Container orchestration rebalancing

How to Fix

Exit code 143 is normal during shutdown. However, you should handle SIGTERM to perform graceful cleanup:

Handle SIGTERM in Node.js

const http = require('http');
const server = http.createServer(app);

process.on('SIGTERM', () => {
  console.log('SIGTERM received. Starting graceful shutdown...');

  server.close(() => {
    console.log('HTTP server closed');
    // Close database connections
    db.end().then(() => {
      process.exit(0);  // Exit with 0 instead of 143
    });
  });

  // Force shutdown after timeout
  setTimeout(() => process.exit(0), 10000);
});

server.listen(3000);

Handle SIGTERM in Python

import signal
import sys

def handle_sigterm(signum, frame):
    print("SIGTERM received, shutting down gracefully...")
    # Close connections, flush buffers
    db.close()
    sys.exit(0)  # Exit with 0 instead of 143

signal.signal(signal.SIGTERM, handle_sigterm)

Ensure signals reach your application

# Bad: shell form wraps in /bin/sh, SIGTERM goes to sh not your app
CMD node app.js

# Good: exec form sends SIGTERM directly to node
CMD ["node", "app.js"]

# If you need shell features, use exec
CMD exec node app.js

# Entrypoint scripts should use exec too
# entrypoint.sh:
#!/bin/sh
exec "$@"   # Replace shell with the CMD process

Use tini as init process

# Install tini to properly forward signals
RUN apk add --no-cache tini
ENTRYPOINT ["tini", "--"]
CMD ["node", "app.js"]

# Or use Docker's built-in init
# docker run --init my-image

Increase stop timeout

# Give the app more time to shut down (default 10s)
docker stop --time=30 <container-id>
# Docker Compose
services:
  app:
    image: my-image
    stop_grace_period: 30s
# Kubernetes
spec:
  terminationGracePeriodSeconds: 30