两套时间要对齐
容器与宿主机共享同一个内核时钟,所以容器内的系统时间与宿主机一致。但日志时间有两个来源:docker logs -t 追加的时间戳由守护进程按 UTC(RFC3339 格式)写入,而应用自己打印在行内的那个时间受镜像里的时区配置影响,可能是本地时间。两者不一致时,要把它们先对齐再并入时间线。
启动锚点
容器重启不会清空 json-file 驱动下的日志,新日志继续追加到同一个文件,所以日志里会同时存在重启前后两个阶段。用 docker inspect 读出 StartedAt 与 FinishedAt,就能把日志切成几段,判断某条记录属于哪一次运行。
基本信息
| 适用平台 | Linux 宿主机上的 Docker Engine、兼容的容器运行时 |
|---|---|
| 带时间戳导出 | docker logs -t 容器名 |
| 时间过滤 | docker logs --since 与 --until,接受时间戳或相对时间 |
| 时区 | docker logs -t 输出为 UTC;应用行内时间取决于镜像配置 |
| 启动锚点 | docker inspect -f '{{.State.StartedAt}}' 容器名 |
典型使用场景
- 确定容器内服务被重启的时间:用 StartedAt 与日志首行时间对照
- 导出某时段日志:用 --since/--until 精确取窗口,避免手工截断
- 区分同一次运行内的先后:以 -t 的 UTC 时间为准,行内时间只作参考
- 判断日志是否有断档:容器重建会换新容器 ID,旧日志不再追加
- 跨主机汇总:统一按 UTC 归一后再与宿主机日志合并
带时间戳导出与锚点
带时间戳导出与锚点
# 导出带 UTC 时间戳的日志片段
docker logs -t --since 2026-01-02T00:00:00 --until 2026-01-02T06:00:00 app 2>&1 | head -30
# 查看容器启动与结束时刻(UTC,带纳秒)
docker inspect -f '{{.State.StartedAt}} {{.State.FinishedAt}}' app
# 确认容器内时区设置,解释行内时间为何与 -t 不同
docker exec app date
docker exec app sh -c 'cat /etc/timezone 2>/dev/null || date +%Z'
# 直接读 json-file 日志文件(需 root)
ls -l /var/lib/docker/containers/<容器ID>/时间来源对照
| 来源 | 时区 | 可信度用法 |
|---|---|---|
| docker logs -t 前缀 | UTC | 跨源对齐的首选基准 |
| 应用行内时间 | 取决于镜像 TZ | 先确认时区,否则会整体偏移 |
| StartedAt/FinishedAt | UTC(纳秒) | 切分运行阶段、判断重启时刻 |
| 宿主机 journald 日志 | 通常本地时间 | 与 -t 对齐后再合并 |
| 日志文件 mtime | 本地时间 | 仅作旁证,写入方式会影响它 |
当日志驱动不是 json-file(例如 journald、syslog、fluentd)时,docker logs 的行为与时间戳格式会不同,排查前先确认该容器使用的日志驱动。
容器被重建(docker rm 后重新 run)会得到新的容器 ID 与新的日志文件,旧日志随容器删除而消失;疑似失陷的容器在处置前先导出日志而不是直接删除。