Docker 容器状态:Up, Exited, Created, Paused 及其生产意义

在使用 Docker 的日常工作中,我们经常需要查看容器的状态来了解其运行情况。docker ps 命令是我们的得力助手,但其输出中的 STATUS 列信息,如 Up, Exited, Created, Paused,各自代表什么含义?尤其是在生产环境中,准确理解这些状态对于监控、故障排查和维护至关重要。

本文将深入浅出地解析 Docker 容器的几种核心状态,并通过实例展示它们在实际场景中的表现,帮助你更有效地管理容器化应用。

核心容器状态解析

1. Up:运行中的中坚力量

这是我们最希望看到的状态,尤其对于需要长时间运行的服务(如 Web 服务器、数据库等)。

  • 含义:容器内的主进程正在正常运行。
  • 表示Up <duration> (e.g., Up 5 minutes, Up 2 days),表示容器已经持续运行了多长时间。
  • 生产关注点
    • 对于服务型容器,Up 是健康的基本标志。
    • 如果一个本应长时间运行的容器频繁地短暂 Up 后变为 Exited,这通常意味着启动失败或内部错误,需要立即排查。

示例:启动一个 Nginx Web 服务器容器。

# 启动一个后台运行的 Nginx 容器,并将宿主机 80 端口映射到容器 80 端口
docker run -d --name webserver -p 80:80 nginx:latest
# 查看运行中的容器
docker ps

输出可能类似:

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                               NAMES
abcdef123456   nginx:latest   "/docker-entrypoint.…"   5 seconds ago   Up 4 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   webserver

这里的 Up 4 seconds 清晰地表明容器正在运行。

2. Exited:任务完成或遭遇不测

当容器的主进程终止时,容器状态会变为 Exited。这个状态本身是中性的,但其退出码 (Exit Code) 包含了关键信息。

  • 含义:容器的主进程已经停止运行。
  • 表示Exited (<exit_code>) <duration> ago (e.g., Exited (0) 5 minutes ago, Exited (137) 1 second ago)。
  • 退出码解读
    • Exited (0)正常退出。通常表示容器内的任务(例如一个批处理脚本、一个短暂的计算任务)已成功完成。
    • Exited (non-zero)异常退出。表示容器因错误、信号中断或其他非正常原因而终止。常见的非零退出码有:
      • 1:通常表示应用程序级的通用错误。
      • 126:命令无法执行(权限问题)。
      • 127:未找到命令。
      • 137:表示容器收到了 SIGKILL 信号 (通常由 kill -9 或 OOM Killer 触发)。
      • 139:表示容器收到了 SIGSEGV 信号 (段错误,通常是应用程序 Bug)。
      • 143:表示容器收到了 SIGTERM 信号 (优雅终止信号,docker stop 默认发送此信号)。
  • 生产关注点
    • 对于一次性任务容器,Exited (0) 是预期结果。
    • 对于本应长时间运行的服务容器,任何 Exited 状态(尤其是非 0 退出码)都意味着故障,需要立即调查。
    • 关键排查命令docker logs <container_id_or_name> 查看容器日志,通常能找到导致退出的原因。docker ps -a 可以查看所有容器,包括已退出的。

示例 1:正常退出 (Exit Code 0)

# 启动一个执行 "sleep 10" 的容器,它将在 10 秒后正常结束
docker run -d --name task_success jasonyin2020/oldboyedu-linux-tools:v0.1 sleep 10
sleep 12 # 等待容器执行完毕

# 使用 -a 参数查看所有容器,包括已退出的
docker ps -a -f name=task_success

输出:

CONTAINER ID   IMAGE                                     COMMAND      CREATED          STATUS                      PORTS     NAMES
06ccf49a8cfc   jasonyin2020/oldboyedu-linux-tools:v0.1   "sleep 10"   12 seconds ago   Exited (0) 2 seconds ago             task_success

Exited (0) 表示 sleep 10 命令成功执行完毕。

示例 2:异常退出 (Exit Code 137)

# 启动一个长时间睡眠的容器
docker run -d --name task_interrupt jasonyin2020/oldboyedu-linux-tools:v0.1 sleep 3600

# 获取容器内主进程的 PID
PID=$(docker inspect --format '{{.State.Pid}}' task_interrupt)

# 在宿主机上强制杀死该进程 (模拟外部中断或 OOM kill)
kill -9 $PID
sleep 2 # 等待容器状态更新

# 查看容器状态
docker ps -a -f name=task_interrupt

输出:

CONTAINER ID   IMAGE                                     COMMAND        CREATED          STATUS                       PORTS     NAMES
11cd4fb3464e   jasonyin2020/oldboyedu-linux-tools:v0.1   "sleep 3600"   About a minute ago   Exited (137) 1 second ago             task_interrupt

Exited (137) 表明容器进程被 SIGKILL 信号强制终止。在生产中,这可能意味着内存不足被 OOM Killer 清理,或者管理员手动干预。

3. Created:万事俱备,只欠启动

这个状态比较少见于直接使用 docker run 的场景,因为它通常一闪而过。

  • 含义:容器已经被 Docker 守护进程创建,相关的文件系统层、网络配置等已准备就绪,但容器的主进程尚未启动
  • 如何产生
    • 使用 docker create 命令显式创建容器,但不启动。
    • docker run 命令执行过程中的一个短暂中间状态(docker rundocker create + docker start)。
  • 生产关注点
    • 如果发现有容器长期处于 Created 状态,通常意味着创建后忘记执行 docker start <container_id_or_name>
    • 在自动化脚本或编排工具中,有时会先 create 再根据条件 start,理解此状态有助于调试部署流程。

示例

# 使用 docker create 创建一个容器,但不启动它
docker create --name task_created jasonyin2020/oldboyedu-linux-tools:v0.1 sleep 3600

# 查看容器状态 (-a 不可少)
docker ps -a -f name=task_created

输出:

CONTAINER ID   IMAGE                                     COMMAND        CREATED         STATUS    PORTS     NAMES
42ab49570891   jasonyin2020/oldboyedu-linux-tools:v0.1   "sleep 3600"   2 seconds ago   Created             task_created

此时容器仅被创建,需要 docker start task_created 才能使其进入 Up 状态。

# 启动已创建的容器
docker start task_created

# 再次查看状态
docker ps -f name=task_created

输出:

CONTAINER ID   IMAGE                                     COMMAND        CREATED              STATUS         PORTS     NAMES
42ab49570891   jasonyin2020/oldboyedu-linux-tools:v0.1   "sleep 3600"   About a minute ago   Up 2 seconds             task_created

现在容器状态变为 Up

4. Paused:冻结状态,保留现场

这个状态表示容器内的所有进程都被暂停 (Frozen)

  • 含义:容器的主进程和所有其他进程都被 Linux 内核的 cgroups freezer 功能挂起,CPU 时间片不再分配给它们。容器的网络、文件系统等资源仍然保留。
  • 表示Up <duration> (Paused) (e.g., Up 5 minutes (Paused))。注意,Up 后面的时间仍然是容器的总运行时间,并非暂停时间。
  • 如何产生/解除
    • docker pause <container_id_or_name>:暂停容器。
    • docker unpause <container_id_or_name>:恢复容器运行。
  • docker stop 的区别
    • pause:冻结进程,内存状态保留,恢复时从暂停点继续。非常快速。
    • stop:发送 SIGTERM (默认) 让进程优雅退出,若超时则发送 SIGKILL。进程终止,内存状态丢失。启动时是全新的进程。
  • 生产关注点
    • 主要用途:非常短期的调试或资源快照。例如,在不停止服务的情况下,临时冻结容器以检查某个特定时刻的内存或进程状态(需要其他工具配合)。
    • 不建议:不建议在生产中长时间 pause 容器作为常规操作。它并不能有效释放大部分资源(如内存),且可能导致客户端连接超时、健康检查失败等问题。维护或升级通常使用 stop/rm/run 或滚动更新策略。
    • docker restart 会重置 Up 的计时,而 pause/unpause 不会。

示例

# 先确保有个运行中的容器 c4 (假设之前已用 run 启动)
docker ps -f name=c4
# CONTAINER ID   IMAGE                                                       COMMAND                  CREATED         STATUS         PORTS                               NAMES
# 63692ba3efe0   registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1   "/docker-entrypoint.…"   5 minutes ago   Up 5 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   c4

# 暂停容器
docker pause c4

# 查看状态
docker ps -f name=c4

输出:

CONTAINER ID   IMAGE                                                       COMMAND                  CREATED         STATUS                  PORTS                               NAMES
63692ba3efe0   registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1   "/docker-entrypoint.…"   6 minutes ago   Up 6 minutes (Paused)   0.0.0.0:80->80/tcp, :::80->80/tcp   c4

注意状态变为 Up ... (Paused)。此时访问该容器的 80 端口会无响应。

# 恢复容器
docker unpause c4

# 再次查看状态
docker ps -f name=c4

输出:

CONTAINER ID   IMAGE                                                       COMMAND                  CREATED         STATUS         PORTS                               NAMES
63692ba3efe0   registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1   "/docker-entrypoint.…"   7 minutes ago   Up 7 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   c4

容器恢复运行,Up 时间继续累计。

其他可能遇到的状态

  • Restarting:当容器配置了重启策略 (--restart 选项) 并在退出后尝试重启时,会短暂显示此状态。
  • Removing:在执行 docker rm 时,容器进入此临时状态,直到资源被清理完毕。

总结:为什么理解容器状态至关重要?

在快节奏的生产环境中,对 Docker 容器状态的深刻理解是高效运维和快速故障定位的基础:

  1. 故障排查Exited (non-zero) 是最直接的警报,引导你通过 docker logs 寻找根本原因。Up 但服务不可用则指向容器内部应用问题或资源瓶颈。
  2. 监控与告警:可以设置监控系统,对非预期的 Exited 状态(尤其是有害的退出码)或长时间运行服务的 Down 状态进行告警。
  3. 自动化部署:CI/CD 流水线或部署脚本需要检查容器状态,以确保部署成功或执行回滚操作。
  4. 资源管理:理解 Paused 状态的资源占用特性,以及 Exited 容器仍占用磁盘空间(需 docker container prune 清理)有助于优化资源利用。
posted on 2025-04-09 18:02  Leo_Yide  阅读(757)  评论(0)    收藏  举报