全部学科
Python全栈
python
NodeJS全栈
nodejs
📅 2026-05-21 6 分钟 ✍️ juanwangdev

优雅启动与关闭

容器优雅停机确保数据一致性,下面介绍信号处理与配置方法。

信号处理

停机流程

dockerfile
docker stop my-app
    ↓
发送 SIGTERM (默认等待 10s)
    ↓
容器处理中请求
    ↓
清理资源(关闭连接、刷盘)
    ↓
进程退出
    ↓
(超时 10s 后)
    ↓
发送 SIGKILL (强制终止)

信号处理示例

JavaScript
# Node.js 应用
FROM node:18

COPY server.js .

# PID 1 问题:shell 不转发信号
# CMD ["node", "server.js"]  # 错误:shell 格式

# 正确:exec 格式
CMD ["node", "server.js"]
Bash
// server.js
process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully');
  server.close(() => {
    console.log('Closed all connections');
    process.exit(0);
  });
});

process.on('SIGKILL', () => {
  console.log('SIGKILL received, forcing exit');
  process.exit(1);
});

stop_grace_period

dockerfile
# 配置超时时间(默认 10s)
docker run -d --name my-app --stop-timeout 30 my-app

# Compose 配置
services:
  app:
    image: my-app
    stop_grace_period: 30s

超时后发送 SIGKILL 强制终止,可能丢失数据。

PID 1 问题

Shell 格式 vs Exec 格式

dockerfile
# Shell 格式(不推荐)
CMD node server.js
# 启动 /bin/sh -c "node server.js"
# SIGTERM 发给 shell,不转发给 node

# Exec 格式(推荐)
CMD ["node", "server.js"]
# 直接启动 node server.js
# SIGTERM 直接发给 node

tini 解决方案

Bash
# 安装 tini
RUN apt-get install -y tini

# 使用 tini 作为 init 系统
ENTRYPOINT ["tini", "--"]
CMD ["node", "server.js"]

tini 是轻量级 init 系统,正确转发信号并回收僵尸进程。

优雅启动

预热检查

Java
#!/bin/bash
# entrypoint.sh

# 预热缓存
echo "Warming up cache..."
curl -s http://localhost:3000/warmup

# 检查依赖
until nc -z db 5432; do
  echo "Waiting for DB..."
  sleep 1
done

echo "Starting application..."
exec "$@"

优雅关闭示例

Java

Python
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
  System.out.println("Shutting down gracefully");
  dataSource.close();
  server.stop();
}));

Python

text
import signal
import sys

def graceful_shutdown(signum, frame):
    print("Shutting down gracefully")
    server.close()
    sys.exit(0)

signal.signal(signal.SIGTERM, graceful_shutdown)

要点总结

  • docker stop 先发送 SIGTERM,等待 10s 后发送 SIGKILL
  • Exec 格式 CMD 确保信号直接传给进程,Shell 格式会被 shell 拦截
  • stop_grace_period 配置超时,避免过早强制终止
  • tini 作为 init 系统正确转发信号并回收僵尸进程
  • 应用需处理 SIGTERM 信号,完成请求处理和资源清理
想在手机上练习这篇文章的配套题目?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码
← 上一篇 健康检查与自愈
下一篇 → 日志聚合与监控栈
扫码体验小程序
加载中
想在手机上刷题学习?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码