Docker 容器停止命令 docker stop 详解与优雅关机实践
Docker stop 命令用于优雅停止容器,默认先向主进程发送 SIGTERM 信号允许清理数据,超时后强制发送 SIGKILL。与 docker kill 直接强制终止不同,stop 提供缓冲时间。可通过 -t 参数调整等待时长。若容器主进程无法处理信号或死锁,需使用 kill。开发者应在应用层监听 SIGTERM 实现优雅退出。

Docker stop 命令用于优雅停止容器,默认先向主进程发送 SIGTERM 信号允许清理数据,超时后强制发送 SIGKILL。与 docker kill 直接强制终止不同,stop 提供缓冲时间。可通过 -t 参数调整等待时长。若容器主进程无法处理信号或死锁,需使用 kill。开发者应在应用层监听 SIGTERM 实现优雅退出。

在 Docker 使用中,如何有效停止容器是运维的重要环节。今天聚焦 docker stop 命令。它融合了'先礼后兵'的完整机制。
很多新手会混淆 docker stop 和 docker kill,甚至觉得它们没什么区别,不都是让容器停止运行吗?如果你也这么想,那就大错特错了。它们的区别,就像是'礼貌地请客人离开'和'直接把客人轰出门外'的本质区别。
docker stop:优雅的绅士
它的工作流程是'先礼后兵'。当你执行 docker stop 时,Docker daemon 会先向容器内的主进程(PID 1)发送一个 SIGTERM 信号。这个信号的意思是:'您好,麻烦您处理一下手头的工作,我们准备要关闭了。'进程收到这个信号后,可以执行一些预定义的清理操作,比如关闭数据库连接、将内存数据持久化到磁盘、完成正在处理的网络请求等。这给了容器一个'体面退出'的机会。只有在等待一段时间(默认 10 秒)后,如果容器依然没有自行停止,Docker 才会失去耐心,发出终极杀手锏——SIGKILL 信号。这个信号是强制性的,操作系统会立即终止该进程,并且进程无法捕获或忽略它。这是一种强制手段。
docker kill:粗暴的霸王
相比之下,docker kill 就直接多了。它默认发送的就是 SIGKILL 信号(也可通过 -s 参数指定其他信号),相当于不由分说,直接拔电源。容器进程没有机会做任何清理工作,可能会导致数据丢失或状态不一致。所以,首选永远是 docker stop!除非容器已经完全无响应,你确认它无法处理 SIGTERM 信号,这时才考虑使用 docker kill 作为最后的补救措施。
光说不练假把式,下面我们通过一系列示例来真切感受 docker stop 的魅力。
启动一个测试容器:我们用一个最简单的 Nginx 容器来演示。它会以后台模式运行。
docker run -d --name my-nginx nginx:alpine
使用 docker ps 查看,确认容器正在运行(STATUS 为 Up)。
优雅地停止它:
docker stop my-nginx
再次运行 docker ps,你会发现容器不见了。运行 docker ps -a 可以看到容器状态变为 Exited (0),其中的 0 表示正常退出码。
假设我们有一个自定义的容器,它收到 SIGTERM 后需要花费 25 秒进行复杂的数据清理工作。默认的 10 秒显然不够。
启动一个模拟'慢'容器:我们可以写一个简单的脚本模拟此行为。
# 创建一个名为 slow-stop.sh 的脚本
cat > slow-stop.sh << 'EOF'
#!/bin/sh
# 模拟收到 SIGTERM 后的清理工作
trap "echo 'Received SIGTERM, cleaning up...'; sleep 25; echo 'Cleanup done!'; exit 0" SIGTERM
echo "Container is running..."
# 保持脚本运行
while true; do
sleep 1
done
EOF
# 构建一个自定义镜像
cat > Dockerfile << 'EOF'
FROM alpine:latest
COPY slow-stop.sh /
RUN chmod +x /slow-stop.sh
CMD ["/slow-stop.sh"]
EOF
docker build -t my-slow-app .
docker run -d --name slow-container my-slow-app
使用默认超时停止(预计会失败):
time docker stop slow-container # 使用 time 命令计算耗时
你会发现大约 10 秒后,命令执行完毕。但使用 docker logs slow-container 查看日志,你会发现只打印了 "Received SIGTERM, cleaning up...",还没来得及打印 "Cleanup done!" 就被 SIGKILL 强制杀死了。它的退出码不会是 0。
使用自定义超时时间:docker stop 命令支持 -t 或 --time 参数来设置等待时间(单位:秒)。
# 重新启动容器
docker start slow-container
# 给予 30 秒的超时时间
time docker stop -t 30 slow-container
这次,命令大约会在 30 秒后完成。查看日志 docker logs slow-container,你会看到完整的 "Cleanup done!" 输出,并且退出码是 0。这证明了优雅关机成功了!
启动容器:
docker run -d --name quick-nginx nginx:alpine
使用 docker kill:
docker kill quick-nginx
这个过程几乎是瞬间完成的。对于 Nginx 这种设计良好的服务,它也能处理 SIGKILL 之外的信号,我们可以通过给 docker kill 指定信号来模拟 stop。
让 docker kill 发送 SIGTERM 信号:
docker run -d --name another-nginx nginx:alpine
docker kill -s SIGTERM another-nginx # 使用 kill 发送 stop 的信号
效果和 docker stop 是一样的。这反过来证明了,docker stop 本质上就是 docker kill -s SIGTERM 加上一个超时等待后自动升级为 SIGKILL 的包装。
这是一个非常实用的运维技巧,可以优雅地停止所有正在运行的容器,而不是粗暴地杀死它们。
docker stop $(docker ps -q)
docker ps -q:-q 参数只输出容器的 ID。docker stop ...:然后将这些 ID 作为参数传递给 stop 命令。docker stop 之后容器去哪了?
容器只是停止了,其文件系统(数据层)和配置(容器名、端口映射等)仍然存在。你可以通过 docker start 再次启动它。只有执行 docker rm 后,容器才会被彻底删除。stop 停不掉?
通常有两个原因:
exec 命令或在更高级的工具中包装进程。docker kill 了。docker restart 是什么?
docker restart = docker stop + docker start。它同样支持 -t 参数,用于控制停止阶段的超时时间。docker stop 远不止是一个命令,它体现了 Docker 设计中对应用生命周期的尊重。理解其 SIGTERM 和 SIGKILL 的两阶段机制,学会灵活运用 -t 参数,并根据不同场景选择 stop 或 kill,是你从 Docker 新手走向熟练玩家的标志。
下次在停止容器时,不妨多一份耐心,给它一个体面退出的机会,毕竟它曾辛勤地为你工作过。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online