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 run≈docker 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 容器状态的深刻理解是高效运维和快速故障定位的基础:
- 故障排查:
Exited (non-zero)是最直接的警报,引导你通过docker logs寻找根本原因。Up但服务不可用则指向容器内部应用问题或资源瓶颈。 - 监控与告警:可以设置监控系统,对非预期的
Exited状态(尤其是有害的退出码)或长时间运行服务的Down状态进行告警。 - 自动化部署:CI/CD 流水线或部署脚本需要检查容器状态,以确保部署成功或执行回滚操作。
- 资源管理:理解
Paused状态的资源占用特性,以及Exited容器仍占用磁盘空间(需docker container prune清理)有助于优化资源利用。
浙公网安备 33010602011771号