内置重启策略种类

Docker提供了四种重启策略:

  1. no - 默认策略,容器退出后不会自动重启
  2. always - 无论容器因何原因退出,都会尝试自动重启
  3. on-failure - 仅当容器以非零状态码退出时(即异常退出)才会重启
  4. unless-stopped - 除非容器被明确停止(如使用docker stop命令),否则总是重启容器

重启策略触发时机

Docker的重启策略会在以下情况下起作用:

1. 容器内部进程退出

  • 当容器中的主进程(PID 1)终止时,根据设置的重启策略决定是否重启容器
  • 例如:应用程序崩溃、内存溢出、进程被意外终止等情况

2. Docker守护进程重启

  • 当Docker守护进程(dockerd)本身重启时
  • alwaysunless-stopped策略的容器会在Docker守护进程重启后自动启动
  • on-failure策略的容器不会因Docker守护进程重启而自动启动

3. 系统重启

  • 当安装Docker的主机系统重启时
  • 如果Docker服务设置为开机自启,则alwaysunless-stopped策略的容器会随Docker服务启动而启动

4. 资源限制导致容器被杀死

  • 当容器因OOM(内存不足)被系统终止时
  • 将根据重启策略决定是否重启容器

主进程是如何被定义的?

在Docker容器中,主进程指的是在容器内运行的PID(Process ID)为1的进程。这个进程有着特殊的地位和重要性。

Docker容器中的主进程通常由以下方式确定:

1. 通过Dockerfile的CMD或ENTRYPOINT指令

# 使用CMD指令设置主进程
CMD ["nginx", "-g", "daemon off;"]

# 或者使用ENTRYPOINT指令
ENTRYPOINT ["java", "-jar", "app.jar"]

当两者同时存在时,ENTRYPOINT定义基本命令,CMD提供默认参数。

2. 通过docker run命令覆盖

# 覆盖默认的CMD
docker run myimage /bin/bash

# 覆盖默认的ENTRYPOINT
docker run --entrypoint /bin/sh myimage

主进程(PID 1)的特殊性

在Docker容器中,主进程具有几个重要特性:

  1. 信号处理责任:PID 1需要正确处理Unix信号(如SIGTERM),否则容器可能无法优雅关闭
  2. 僵尸进程回收:负责”收养”并清理容器内的僵尸进程(zombie processes)
  3. 容器生命周期:主进程退出意味着整个容器停止
    • 当PID 1退出时,Docker会根据重启策略决定是否重启容器
    • 主进程的退出状态码决定容器是否被视为正常退出
  4. 健康检查:健康检查通常针对主进程提供的服务进行监控

常见的错误设置

1.使用shell形式而非exec形式

# 错误方式(shell形式) - /bin/sh成为PID 1
CMD nginx -g "daemon off;"

# 正确方式(exec形式) - nginx成为PID 1
CMD ["nginx", "-g", "daemon off;"]

2.使用非守护进程工具作为入口点

# 不具备信号处理能力的脚本作为PID 1
CMD ["start.sh"]

健康检查

Docker 健康检查

# 定义健康检查 HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1

Shell 脚本

#!/bin/bash
set -e

# 启动您的服务并放入后台
your-service &
SERVICE_PID=$!

# 监控服务
while true; do
    if ! kill -0 $SERVICE_PID 2>/dev/null; then
        echo "服务已停止,正在重启..."
        your-service &
        SERVICE_PID=$!
    fi
    sleep 5
done

Supervisor

s6-overlay

nodejs - pm2