Linux默认的时区是UTC,所以在创建Docker容器时我们会添加一个环境变量TZ=Asia/Shanghai来指定容器的时区,但是偶然发现直接指定TZ环境变量为Asia/Shanghai后date命令输出的时间依然是UTC时间,于是去研究了一下这个环境变量。

TZ环境变量如何使用

TZ是POSIX标准中定义的一个标准环境变量,用来覆盖各种与时间有关的函数的默认时区。在Linux中,基本是GNU C 库glibcglibcTZ环境变量有2种写法:

  1. std offset[dst[offset][,start[/time],end[/time]]],如国内的时区对应为CTS-8
  2. :[filespec],这是最常见的一种,如Asia/Shanghai

对于TZ环境变量的解释为:

  • 如果使用的filespec格式,对于:/开头的,会去读取指定路径的tzfile格式的时区文件来读取时区信息;对于:开头的会去系统时区目录读取时区文件,即/usr/share/zoneinfo/;对于:也没有,只有一个filespec的,比如常见的TZ=Asia/Shanghai,会尝试上面两种TZ环境变量的格式

  • 如果TZ环境变量没有被设置,则使用默认时区,默认时区TZ=:/etc/localtime ,通过将tzfile格式的文件复制或者软连接到/etc/localtime来配置默认时区,比如:ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

  • 如果TZ环境变量被设置了但是内容为空,或者设置了但是无法被解析,则使用UTC

不是每个镜像都打包了tzfile时区文件

对于一些特殊的镜像,不一定会带时区文件,可以用以下命令测试

1
docker run --rm 镜像名 ls -lah /usr/share/zoneinfo/Asia/Shanghai

带时区文件的常见的,比如

  • mysql

  • redis

也有一些不带的,比如

  • alpine

所以为了保证TZ环境变量能够生效,使用CST-8这种会好一些

https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html

https://xy2401.com/local-docs/gnu/manual.zh/libc/TZ-Variable.html

https://man.archlinux.org/man/tzset.3

https://codesearch.debian.net/search?q=%2Fetc%2Ftimezone