Docker checkpoint功能默认不可用,需同时满足三个前提:安装CRIU≥3.15、Docker daemon启用experimental模式、/etc/docker/daemon.json中设"experimental":true;缺一即报错或静默禁用。

Checkpoint 功能在 Docker 中默认不可用
Docker 原生不支持 docker checkpoint,必须依赖底层 runc 和 CRIU,并手动启用实验性功能。如果你执行 docker checkpoint create 报错 “command not found” 或 “feature disabled”,不是命令写错了,而是 Docker daemon 根本没开启 checkpoint 支持。
关键前置条件有三个:criu 已安装且版本 ≥ 3.15(推荐 3.17+),Docker 启动时加了 --experimental,且 /etc/docker/daemon.json 中明确设 "experimental": true。缺一不可。
常见坑:
-
criu安装后未加入$PATH,Docker 启动时找不到二进制,但不会报错,只静默禁用 checkpoint - 修改
daemon.json后忘记sudo systemctl restart docker,配置不生效 - 容器启动时用了
--privileged或挂载了/dev、/proc等敏感路径,CRIU 拒绝 checkpoint(提示dump failed: exited with error)
创建 checkpoint 必须满足容器运行约束
不是所有容器都能被 checkpoint。CRIU 要求进程处于“可冻结”状态:不能有用户态线程、不能使用某些内核特性(如 AF_UNIX abstract socket、memfd_create)、不能有打开的 inotify 实例等。最稳妥的做法是用极简镜像启动测试容器,例如:
docker run -d --name chktest --security-opt seccomp=unconfined alpine:latest sleep 3600
注意点:
- 必须去掉
--restart策略,否则 checkpoint 后恢复可能触发自动重启,干扰状态一致性 - 避免挂载宿主机
/sys、/run或使用tmpfs,这些会引入不可序列化的内核对象 - 如果容器内主进程是 shell(如
sh -c "while true; do ..."),CRIU 可能因信号处理异常失败,建议用单进程模型(如直接跑sleep或nginx -g "daemon off;")
checkpoint 目录权限和路径必须由 Docker 管理
Docker 不允许指定任意路径保存 checkpoint,必须用 docker checkpoint create --checkpoint-dir 指向一个已存在的、Docker daemon 有读写权限的目录,且该目录不能是符号链接或 NFS 挂载点——CRIU 需要稳定的 inode 和本地文件系统语义。
典型安全做法:
- 创建专用目录:
sudo mkdir -p /var/lib/docker/checkpoints - 确保属主为
root:root,权限700 - 执行:
docker checkpoint create --checkpoint-dir /var/lib/docker/checkpoints chktest chk1
若提示 permission denied on checkpoint dir,大概率是 SELinux 启用中,需临时设为 permissive:sudo setenforce 0(生产环境应配对应策略而非关闭)。
restore 时容器 ID 和网络状态不会自动还原
checkpoint 只保存进程内存、寄存器、打开文件描述符、TCP 连接状态等,不保存容器元数据(如 IP 地址、端口映射、卷挂载点)。执行 docker start --checkpoint chk1 chktest 会复用原容器配置,但若原容器已被 rm,则必须用 docker run --rm --name chktest --checkpoint chk1 ... 重建,且需严格匹配原始 docker run 参数(包括 -v、--net、--ip 等),否则 restore 失败或行为异常。
特别注意:
- restore 前必须确保目标宿主机安装了完全一致的
criu版本,否则可能因 ABI 不兼容导致段错误 - 跨机器迁移时,CPU 微架构差异(如从 Intel 迁到 AMD)虽通常可行,但若容器用了 AVX-512 指令,restore 会崩溃,CRIU 日志里会出现
Illegal instruction - checkpoint 文件夹(如
/var/lib/docker/checkpoints/chktest/chk1)包含几十个二进制和元信息文件,迁移时必须整目录拷贝,不能只传其中几个
真正麻烦的从来不是命令怎么敲,而是确认 CRIU 能否干净地冻结那个特定进程——它对内核版本、glibc、甚至 Go runtime 的 GC 行为都敏感。调试时优先看 /var/log/syslog 或 journalctl -u docker | grep criu,而不是只盯着 Docker CLI 的返回码。


















