如何确保 Docker 容器的正确关闭

DockerDockerBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

Docker 容器已成为现代软件开发和部署中不可或缺的一部分。确保这些容器正确关闭对于维护可靠性、防止数据丢失以及确保应用程序生命周期顺利进行至关重要。本教程将指导你了解 Docker 容器的生命周期,实现容器的优雅关闭,并处理各种关闭场景,以优化你的容器管理。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker/ContainerOperationsGroup -.-> docker/start("Start Container") docker/ContainerOperationsGroup -.-> docker/stop("Stop Container") docker/ContainerOperationsGroup -.-> docker/restart("Restart Container") docker/ContainerOperationsGroup -.-> docker/logs("View Container Logs") docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") subgraph Lab Skills docker/start -.-> lab-415173{{"如何确保 Docker 容器的正确关闭"}} docker/stop -.-> lab-415173{{"如何确保 Docker 容器的正确关闭"}} docker/restart -.-> lab-415173{{"如何确保 Docker 容器的正确关闭"}} docker/logs -.-> lab-415173{{"如何确保 Docker 容器的正确关闭"}} docker/inspect -.-> lab-415173{{"如何确保 Docker 容器的正确关闭"}} end

理解 Docker 容器生命周期

Docker 容器旨在实现轻量级、可移植和可扩展。它们为运行应用程序提供了一致且隔离的环境,使得软件开发、部署和管理变得更加容易。然而,理解 Docker 容器的生命周期对于确保正在运行的进程正确关闭和优雅终止至关重要。

Docker 容器生命周期

Docker 容器的生命周期可分为以下几个阶段:

  1. 创建:Docker 容器从 Docker 镜像创建而来,该镜像充当容器的模板。
  2. 运行:容器启动,主进程(在镜像中指定)开始执行。
  3. 暂停:容器可以被临时暂停,允许主进程在保留容器状态的同时被挂起。
  4. 停止:容器被停止,这会向主进程发送一个 SIGTERM 信号,使其能够优雅地关闭。
  5. 重启:已停止的容器可以被重启,恢复主进程的执行。
  6. 删除:容器可以被删除,从系统中永久删除。
graph LR A[创建] --> B[运行] B --> C[暂停] B --> D[停止] D --> B[重启] B --> E[删除]

处理容器关闭

当 Docker 容器停止时,容器内运行的主进程会收到一个 SIGTERM 信号,这是用于请求优雅关闭的默认信号。然后,该进程应在退出之前执行任何必要的清理任务,例如保存数据、关闭连接或释放资源。

如果主进程在指定的超时时间(默认是 10 秒)内没有退出,Docker 将发送一个 SIGKILL 信号,强制终止该进程。如果进程未能正确清理,这可能会导致数据丢失或其他问题。

为确保正确关闭,设计你的应用程序以处理 SIGTERM 信号并执行优雅关闭非常重要。这可以通过在应用程序代码中实现信号处理程序,或使用像 tinidumb-init 这样的进程管理器来代表主进程处理信号来实现。

## 以 tini 作为 Docker 容器入口点的示例
ENTRYPOINT ["/usr/bin/tini", "--", "your-application-command"]

通过理解 Docker 容器生命周期并正确处理关闭过程,你可以确保在 Docker 容器中运行的应用程序能够安全地停止和重启,而不会丢失数据或遇到其他问题。

容器的优雅关闭

确保 Docker 容器优雅地关闭对于维护应用程序及其管理的数据的完整性至关重要。当容器停止时,容器内运行的主进程应有机会执行任何必要的清理任务,例如保存数据、关闭连接或释放资源。

处理 SIGTERM 信号

默认情况下,当 Docker 容器停止时,容器内运行的主进程会收到一个 SIGTERM 信号。此信号用于请求进程进行优雅关闭。为确保正确关闭,你的应用程序应设计为处理 SIGTERM 信号并在退出前执行必要的清理任务。

以下是在 Python 应用程序中处理 SIGTERM 信号的示例:

import signal
import time

def graceful_shutdown(signum, frame):
    print("收到 SIGTERM,正在执行优雅关闭...")
    ## 在此处执行清理任务
    time.sleep(5)  ## 模拟清理任务
    print("优雅关闭完成。")
    exit(0)

signal.signal(signal.SIGTERM, graceful_shutdown)

## 主应用程序逻辑
while True:
    print("应用程序正在运行...")
    time.sleep(1)

在此示例中,graceful_shutdown 函数被注册为 SIGTERM 信号的处理程序。当容器停止时,将调用此函数,使应用程序在退出前执行任何必要的清理任务。

自定义关闭超时时间

默认情况下,Docker 在收到 SIGTERM 信号后将等待 10 秒让主进程退出。如果进程在此超时时间内未退出,Docker 将发送一个 SIGKILL 信号,强制终止该进程。

你可以在启动 Docker 容器时使用 --stop-timeout 标志来自定义关闭超时时间:

docker run -d --stop-timeout 20 your-image

这将把关闭超时时间增加到 20 秒,为主进程提供更多时间来执行优雅关闭。

使用进程管理器

另一种确保优雅关闭的方法是使用进程管理器,例如 tinidumb-init,作为容器的入口点。这些进程管理器旨在处理信号并将其转发到主进程,确保正确的关闭顺序。

## 以 tini 作为 Docker 容器入口点的示例
ENTRYPOINT ["/usr/bin/tini", "--", "your-application-command"]

通过使用进程管理器,你可以简化应用程序中的信号处理,并依靠进程管理器代表你处理关闭过程。

通过理解并实现优雅关闭机制,你可以确保 Docker 容器能够安全地停止和重启,而不会丢失数据或遇到其他问题。

处理关闭场景

在使用 Docker 容器时,你可能会遇到各种需要不同处理方法的关闭场景。了解这些场景以及如何处理它们对于确保应用程序的可靠性和稳定性至关重要。

优雅关闭

如前所述,关闭 Docker 容器的推荐方法是处理 SIGTERM 信号并执行优雅关闭。这允许主进程清理资源、保存数据并以可控的方式退出。

强制关闭(SIGKILL)

如果主进程在指定的关闭超时时间(默认是 10 秒)内没有退出,Docker 将发送一个 SIGKILL 信号,强制终止该进程。如果进程未能正确清理,这可能会导致数据丢失或其他问题。

要处理这种情况,你可以:

  1. 在启动容器时使用 --stop-timeout 标志增加关闭超时时间。
  2. 确保你的应用程序设计为处理 SIGTERM 信号并在规定时间内执行优雅关闭。
  3. 使用像 tinidumb-init 这样的进程管理器来代表你的应用程序处理信号转发和关闭过程。

容器重启策略

Docker 提供了各种重启策略,这些策略决定了容器停止时应如何表现。可以在使用 --restart 标志启动容器时设置这些策略。一些常见的重启策略包括:

  • no:容器不会自动重启。
  • always:无论退出状态如何,容器都会一直重启。
  • on-failure:只有当容器以非零状态退出时才会重启。
  • unless-stopped:除非容器被明确停止(例如,使用 docker stop),否则它会重启。

选择合适的重启策略有助于确保你的应用程序始终可用,并能抵御意外的关闭或故障。

## 设置重启策略的示例
docker run -d --restart=on-failure:5 your-image

在此示例中,如果容器以非零状态退出,它将最多重启 5 次。

通过理解并正确处理各种关闭场景,你可以确保 Docker 容器能够安全地停止和重启,将数据丢失或其他问题的风险降至最低。

总结

在本教程中,你已经学习了如何确保 Docker 容器的正确关闭。通过理解容器生命周期、实施优雅关闭技术以及处理各种关闭场景,你可以优化容器管理,以提高可靠性、正常运行时间和整体应用程序稳定性。应用这些最佳实践将帮助你维护一个强大且有弹性的基于 Docker 的基础设施。