bigywater.tech
Docker · 94

容器的时间:时钟共享、时区与 TZ

容器的时间从哪来?为什么 alpine 里设了 TZ 却还是 UTC?容器能改系统时间吗?日志时间戳按哪个时区?这篇逐项实测。

偏移 0
容器的时间命名空间里 monotonic 和 boottime 的偏移
CST-8 有效
alpine 里 TZ=Asia/Shanghai 不生效,POSIX 写法 CST-8 生效
UTC
docker logs -t 的时间戳与 docker inspect 的 StartedAt 的时区

时钟

实测 · 本机执行输出
  容器里 Python 的 time.time_ns() 相对 Mac 上调用前后时间的中点,差值(毫秒,7 次;docker exec 的往返不对称,所以只能看量级):[28, 19, 17, 18, 20, 17, 27]
  虚拟机里的 date +%s 与容器一致吗?虚拟机 1791643349,容器 1791643350(两次命令之间有间隔)
  时间命名空间:容器 /proc/self/ns/time = time:[4026535132];虚拟机 PID 1 的 = time:[4026531834]
  容器的时间命名空间偏移 /proc/self/timens_offsets:monotonic           0         0 ; boottime            0         0
  容器里 /proc/uptime 的开机时间(秒) = 19317;虚拟机 = 19317(容器的 uptime 是虚拟机的,不是容器自己的)

容器没有自己的时钟:读到的就是虚拟机内核的时间。容器有独立的时间命名空间,但没有设置偏移,所以时钟和 uptime 都和虚拟机一致(uptime 是 19317 秒,不是容器自己的运行时间)。

时区

实测 · 本机执行输出
  默认容器的 date:Sat Oct 10 14:42:31 UTC 2026;TZ 未设置
  Mac 上的 date:Sat Oct 10 22:42:31 CST 2026
  -e TZ=Asia/Shanghai(alpine 镜像里没有 /usr/share/zoneinfo):Sat Oct 10 14:42:31 UTC 2026
  -e TZ=CST-8(POSIX 写法,不需要时区数据库):Sat Oct 10 22:42:31 CST 2026
  python:3.12-alpine 有 /usr/share/zoneinfo?/usr/share/zoneinfo;-e TZ=Asia/Shanghai:Sat Oct 10 22:42:32 CST 2026
  Python 的 datetime.now() 在 TZ=Asia/Shanghai 的容器里:2026-10-10T22:42:32 ('CST', 'CST')
  -v /etc/localtime:/etc/localtime:ro(Mac 的 /etc/localtime 是指向 /var/db/timezone/… 的符号链接):退出码 0;Sat Oct 10 22:42:33 CST 2026

Alpine 镜像里没有时区数据库,TZ=Asia/Shanghai 查不到,于是退回 UTC;用 POSIX 写法 TZ=CST-8、安装 tzdata、挂宿主的 /etc/localtime,或用自带 zoneinfo 的镜像(python:3.12-alpine)都可以。

改时间

实测 · 本机执行输出
  date -s "2000-01-01 00:00:00"(默认没有 CAP_SYS_TIME):退出码 0;输出:Sat Jan  1 00:00:00 UTC 2000 ⏎ date: can't set date: Operation not permitted
  紧接着再看容器里的 date:Sat Oct 10 14:42:33 UTC 2026(时间没有被改)
  容器的 capability 里有 sys_time 吗?没有

默认没有 CAP_SYS_TIME,date -s 被拒绝,而且改的是整个虚拟机的时钟(所以我没有去加这个 capability 测试)。

日志

实测 · 本机执行输出
  容器自己 date 的输出:Sat Oct 10 22:42:33 CST 2026;docker logs -t 给的时间戳:2026-10-10T14:42:33.557078303Z
  docker inspect StartedAt = 2026-10-10T14:42:33.506721678Z

docker 自己打的时间戳(logs -t、StartedAt、events)是 UTC,不随容器的 TZ。程序自己打印的时间才随 TZ。

分步演示

容器的时间
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。时间差用 Python 的 time.time_ns() 取 docker exec 前后 Mac 时间的中点比较;时区实验用 alpine:3.20 与 python:3.12-alpine;没有给任何容器加 SYS_TIME(会改动虚拟机时钟);实验后已删除容器
    • 没有验证:Mac 睡眠唤醒后虚拟机时钟的校正、NTP 同步、CLONE_NEWTIME 偏移的设置方法(docker 没有提供)、Linux 宿主机上 /etc/localtime 的挂载、tzdata 的安装方式差别
    京ICP备2026067502号-1京公网安备11010502063487号