本节摘要:观测词条回答"容器现在怎么样了":docker ps 列出存量与端口映射,docker stats 报实时资源占用,docker logs 取进程输出,docker top 看容器内部进程树。本节讲各词条的输出读法、过滤器与格式化用法,并给出一套"从异常症状到证据命令"的固定路径。
别以为 ps 只是列个清单:它输出的每一列都是证据——STATUS 里的重启次数、PORTS 里的映射方向、NAMES 里的命名规律,排障时全用得上。3.1 与 3.2 造出来的容器,从这里开始被持续观察。观测词条的共同特点是零风险、只读、高频,值得练到肌肉记忆级。
docker ps [OPTIONS]
义项:
| 选项 | 含义 | 使用时机 |
|---|---|---|
| 无参数 | 只列 running 容器 | 日常盘点 |
-a |
含停止的容器 | 找尸体 |
-q |
只输出 ID | 配合批量操作 |
--filter |
按状态、名字、标签等过滤 | 精确定位 |
--format |
Go 模板定制列 | 脚本与巡检 |
-n 数量 |
限最近创建的若干条 | 只看新增 |
$ docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' NAMES STATUS PORTS web Up 3 days (healthy) 0.0.0.0:8080->80/tcp order-api Up 2 hours (unhealthy) 127.0.0.1:9000->9000/tcp cache Restarting (1) 4 s ago batch Exited (137) 20 hours ago init-job Exited (0) 22 hours ago
逐行解读这份巡检表。Up 后括号里的 healthy/unhealthy 来自健康检查配置(词条在捌部);cache 的 Restarting (1) 括号是上次退出码,配合不停增长的秒数,就是 3.1 说的重启风暴现场;Exited (137) 里的 137 等于 128 加 9,意味着进程被 SIGKILL 处决——典型成因是内存超限被内核杀掉;Exited (0) 则是体面退场,一次性任务跑完本该如此。一个 STATUS 列,半部排错教材。
$ docker ps --filter status=exited --filter exited=137 -q b71f0a9c3e2d $ docker ps --filter label=team=pay --format '{{.Names}}' pay-gw pay-job
过滤器可叠加:状态加退出码一步锁定被杀的容器;label 过滤在生产里按业务标签圈容器,比记名字可靠。
docker stats [OPTIONS] [CONTAINER...]
义项:无参数刷新全部运行中容器的实时表;--no-stream 只取一次快照,适合脚本;末尾给容器名则只盯目标。
$ docker stats --no-stream NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O web 0.14% 18.4MiB / 3.7GiB 0.49% 1.2GB / 2.9GB 88MB / 12MB order-api 132.7% 502MiB / 512MiB 98.1% 480MB / 512MB 1.1GB / 220MB
这份快照信息量很大:order-api 的 CPU 越过容器配额对应的水位,内存 98.1% 贴着 512MiB 的上限——对照 3.2 给它加的 --memory 512m,下一步要么扩配额要么查泄漏;NET I/O 的收发严重不对称,也在提示异常。stats 与宿主机 top 的差别在于它是按容器聚合的视图,且 LIMIT 列直接对照你的资源配额,超没超一眼可见。
docker logs [OPTIONS] CONTAINER
义项:
| 选项 | 含义 | 使用时机 |
|---|---|---|
-f |
持续跟踪输出 | 复现问题时 |
-n 行数 / --tail |
只取尾部 | 先看最近发生了什么 |
-t |
附时间戳 | 对齐多源日志 |
--since / --until |
时间窗过滤 | 事后再取证 |
--details |
附环境变量等extra信息 | 深挖 |
$ docker logs order-api -n 20 -t 2026-09-03T11:02:41.120 [INFO] order #8842 committed 2026-09-03T11:02:44.377 [WARN] db pool 47/50 busy 2026-09-03T11:02:45.912 [ERROR] db: connection reset by peer 2026-09-03T11:02:45.915 [FATAL] unreachable dependencies, exiting $ docker logs order-api --since 30m | grep -c ERROR 27
取证路径固定:先 -n 看尾部拿直接死因(FATAL 行),再 --since 拉宽时间窗统计频次(半小时里ERROR 出现了成规模次数,说明连接早就在恶化,FATAL 只是最后一根稻草)。logs 读的是容器主进程的标准输出与标准错误——所以镜像里把日志打进文件而stdout 不出的服务,logs 会是空的,这属于镜像构建问题,回到贰部改 Dockerfile 或启动参数。
⚠️ 常见坑:日志文件本身会无限增长,长期主机要给守护进程配置轮转上限,否则磁盘被日志吃满,症状与镜像堆积一模一样。清理命令与配置现场在捌部治理一节。
docker top CONTAINER [ps OPTIONS]
$ docker top web -eo pid,ppid,cmd PID PPID CMD 4102 4075 nginx: master process nginx -g daemon off; 4138 4102 nginx: worker process 4139 4102 nginx: worker process
top 看容器内部进程树:master 与 worker 的父子关系一目了然,PID 是宿主机视角的进程号(进容器 exec ps 看到的是另一套命名空间的编号)。判断"容器里到底跑着几个进程"它是权威——多出来的可疑进程往往是安全事件的信号。stats、logs、top 三个词条各看一面:资源、输出、进程,合起来才是容器的完整体检。
观测发现问题之后,靠什么修?很多时候答案是换镜像或调参数,而镜像从哪来、推到哪去,要过仓库这道关——肆部开讲。