Strategies for Graceful Shutdown
When it comes to gracefully shutting down long-running Docker containers, there are several strategies you can employ to ensure a smooth and controlled shutdown process. This section will explore some of the key strategies and best practices for graceful shutdown.
Signal Handling in Your Application
One of the most important strategies for graceful shutdown is to implement signal handling in your application. This involves writing code that listens for the SIGTERM
(or alternative) signal and performs the necessary cleanup tasks before the application exits.
Here's an example of how you might implement signal handling in a Node.js application:
process.on('SIGTERM', () => {
console.log('Received SIGTERM signal, starting graceful shutdown...');
// Perform cleanup tasks, such as:
// - Saving in-memory data to persistent storage
// - Closing network connections or database connections
// - Flushing logs or other output
// - Performing any other application-specific cleanup tasks
console.log('Graceful shutdown complete, exiting process.');
process.exit(0);
});
By implementing this signal handling, your application can ensure that it performs a controlled shutdown, minimizing the risk of data loss or other issues.
Using Healthcheck and Liveness Probes
Another strategy for graceful shutdown is to use Docker's built-in health check and liveness probe features. These features allow you to define checks that Docker can use to determine the health and readiness of your container.
During the shutdown process, you can use these probes to signal to Docker that your container is in the process of shutting down, allowing Docker to wait for the shutdown to complete before removing the container.
Here's an example of how you might configure a health check and liveness probe in your Docker container:
## Dockerfile
FROM node:14-alpine
COPY . /app
WORKDIR /app
CMD ["node", "server.js"]
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -f http://localhost:3000/healthz || exit 1
LABEL com.labex.shutdown.signal=SIGINT
LABEL com.labex.shutdown.timeout=60
In this example, the HEALTHCHECK
instruction defines a health check that checks the /healthz
endpoint on the container's web server. The LABEL
instructions define the signal to be used for graceful shutdown (SIGINT
) and the timeout period (60 seconds).
During the shutdown process, your application can update the health check endpoint to signal that the shutdown is in progress, allowing Docker to wait for the shutdown to complete before removing the container.
Leveraging Orchestration Frameworks
If you're running your Docker containers in an orchestration framework like Kubernetes or Docker Swarm, you can leverage the built-in features of these frameworks to help with graceful shutdown.
For example, in Kubernetes, you can use the preStop
hook to execute a command or script that performs cleanup tasks before the container is terminated. You can also use the terminationGracePeriodSeconds
field to specify the amount of time the container should be given to shut down gracefully.
Here's an example of how you might configure a Kubernetes deployment with a preStop
hook and a graceful termination period:
## kubernetes-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:latest
ports:
- containerPort: 3000
lifecycle:
preStop:
exec:
command: ["/app/shutdown.sh"]
terminationGracePeriodSeconds: 60
In this example, the preStop
hook runs a script (/app/shutdown.sh
) that performs any necessary cleanup tasks before the container is terminated. The terminationGracePeriodSeconds
field gives the container 60 seconds to shut down gracefully before it is forcibly terminated.
By leveraging these orchestration framework features, you can further enhance the reliability and predictability of your container shutdown process.