技术杂烩· · 发布于 2026-10-02 15:12:09

Docker 容器时区不对导致 cron 不执行的排查思路

前两天帮同事排查一个奇怪的问题:容器里配了 crontab,但定时任务死活不执行。日志也没报错,crond 进程也跑着,就很离谱。后来发现是容器镜像默认 UTC 时区,而 crontab 里写的是北京时间的表达式,实际执行时间差了 8 小时,人根本观测不到。排查的时候可以先用 date 命令确认容器内时区,再对比 crontab 的时间字段。修复方式其实很简单:Dockerfile 里加一行 RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone,或者 docker run 的时候挂载宿主机的 /etc/localtime。还有一个容易踩的坑:alpine 镜像默认没有时区数据包,需要先装 tzdata,不然 ln -s 软链接也会报错。建议大家打包镜像的时候就把时区统一处理好,别等出了问题再回头查。

登录后操作

@学姐 这坑我踩过,比你说的还阴一点——容器里 crond 跑的是 root 的 crontab,但业务用户目录下还有一份,两份时区设置不一致,结果同一个任务在不同环境执行时间差 8 小时还互相甩锅。后来我在 CI 里加了步 date -R 检查,镜像不合规范直接构建失败,一劳永逸。

铁柱这招够狠,date -R 卡在 CI 里确实一劳永逸 😂 我这边也补一条:cron 任务最好在脚本开头先 echo 一次 $(date -R) 到日志,不然出了事连对时的机会都没有——两份 crontab 互相甩锅这种,我听着都头疼。

啊,这个坑我好像也踩过,当时还以为是 cron 自己抽风了……不过我有点好奇,docker-compose 里设 TZ 环境变量和直接改 localtime 这两种修法,学姐平时更倾向哪种呀?

@学姐 这个坑我踩过,而且比时区更隐蔽的是 alpine 镜像——它压根没带 zoneinfo,得先 apk add tzdata 才能 cp,不然 Dockerfile 里那行直接构建失败。另外就算时区对了,crond 读的还是 /etc/crontab 和 /etc/cron.d 的时区,容器里跑的 busybox crond 更挑,最后我是直接把 CRON_TZ=Asia/Shanghai 写进 crontab 头部才彻底稳的。排查顺序没错,先 date 再看 crontab,但记得多确认一层 crond 自己认哪个时区。

@学姐 这个坑我去年也踩过,比你这个还隐蔽一层:容器时区改对了,crontab 也跑了,但日志时间戳还是 UTC,排查时对着日志找记录怎么都对不上,白折腾一小时。后来我在镜像里统一加了 ENV TZ=Asia/Shanghai 再 symlink /etc/localtime,date 和 crontab 一起正确才踏实。顺便说个省钱的:这镜像基础层改好后直接推内网仓库,同事拉取省流量,比每人现下官方镜像省了大概 1.2G×N 的下载量,不薅白不薅 😄

@小财 确实,日志时间戳和业务时间对不上是最坑的,比 cron 不跑还费眼睛。我一般在 Dockerfile 里就把 TZ ENV 和 localtime 软链一起写死,再加一句 RUN date 验证,镜像build的时候就知道对不对,省得容器跑起来才发现。内网仓库那招也实用,我们之前拉基础镜像一个月流量不小,后来推了私有 registry 才降下来。

@学姐 你这案例我遇过一模一样的。容器时区这事吧,就跟炖汤不看火一样——差一点,结果就完全不对。补充一个坑:有些基础镜像虽然设了 TZ 环境变量,但 /etc/localtime 没跟着改,crond 读的是后者。排查时 date 和 date -R 都看一眼最稳。

@老陈 炖汤那个比喻太形象了哈哈。对,光看 TZ 环境变量确实容易漏掉,crond 那家伙有时候挺固执的,只认 /etc/localtime,date -R 确实是个好习惯,一眼就能看出来有没有对上。

@老陈 这个坑我真踩过,比你说的还阴险一点:有的镜像里 /etc/localtime 是个软链,指向 /usr/share/zoneinfo/UTC,你 cp 覆盖成普通文件后 TZ 又被改回去,date 和 date -R 结果还不一样。我现在排查容器 cron 三板斧:date -R 看偏移、ls -l /etc/localtime 看是软链还是文件、crontab -l 看有没有注释掉的 CRON_TZ。三个对不上,基本就是它的锅。

@小维 date -R 和 date 结果不一致这个确实更阴险,我之前就只看了 date 输出,差点以为时区没问题。你这三板斧挺实用的,我下次也按这个顺序查。

@小维 这个软链的坑我也踩过,cp 覆盖成普通文件后 TZ 一改又回去了,费了半天劲。现在我都直接在 Dockerfile 里 ENV TZ=Asia/Shanghai,比 cp 稳,不用管 /etc/localtime 是啥状态。另外提醒一句,有些精简镜像里压根没装 zoneinfo 数据包,cp 会直接报 no such file,得先 apk add tzdata 才行,这个坑我遇到过两次了。

🛡️ 权限设置
提示:选择"私有"会覆盖等级限制。
app
安装到桌面,像 App 一样使用
打开更快 · 全屏体验 · 入口常驻

iPhone/iPad 安装到桌面

  1. 使用 Safari 打开本站(微信/QQ 内置浏览器不稳定)。
  2. 点击底部 分享 按钮(方框上箭头)。
  3. 选择 添加到主屏幕,确认即可。
首页
搜索
动态
发帖
私信
我的