Docker 容器中设置时区

在 linux 中, 通过 /etc/timezone 这个文件设置。 可以通过如下命令 持久化 时区设置, 其中 Asia/Shanghai 是我们需要的时区。

1
cp -a /usr/share/zoneinfo/Asia/Shanghai /etc/timezone

容器中设置时区一直是独立于宿主机的。 可以通过挂载 /etc/timezone 的方式保持与宿主机时间一致。

1
docker run --rm -it -v /etc/timezone:/etc/timezone debian bash

这种方法只适合 本地的、简单的、临时的 容器。

容器有一个很重要的特点, 就是 一处编译, 处处运行。 另外, 容器运行环境本身应该是 独立/隔离 的, 即使是时区也不应该依赖于宿主机。

通过 TZ 环境变量 设置时区

在 Linux 中, 还可以通过 TZ 这个环境变量来设置时区。 但是这种设置并不能实现持久化, 只能在 当前进程和其子进程 中生效。

1
export TZ=Asia/Shanghai

这种方式在 Linux 系统中不合适, 但是在容器中却相当合适。 因为容器核心就是 单进程应用, 不会像 Linux 系统上启动很多。

1
2
3
4
5
6
$ date
Wed Dec 21 14:06:44 UTC 2022

$ export TZ=Asia/Shanghai
$ date
Wed Dec 21 22:06:52 CST 2022

如果需要是用 TZ 环境变量 实现时区控制, 需要安装 tzdata 这个包。

debian/ubuntu 中安装。

debian 的基础镜像默认情况下已经安装了 tzdata,而 ubuntu 并没有。 tzdata 安装时有交互操作, 需要选择默认时区。 通过 DEBIAN_FRONTEND=noninteractive 进入非交互模式, 直接安装。

1
DEBIAN_FRONTEND=noninteractive apt install -y tzdata

alpine 中安装

1
apk add --no-cache tzdata

容器中通过 TZ 环境变量 实现时区控制

  1. 我们需要在构建业务镜像的时候安装 tzdata 并设置 默认时区
  2. 在容器启动的时候, 根据需要再通过注入环境变量的方式设置时区。

Dockerfile 以 nginx:debian 为例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
FROM nginx:1.23 

# 安装 tzdata
RUN apk update \
    && DEBIAN_FRONTEND=noninteractive apt install -y tzdata \
    && rm -rf /var/lib/apt/lists/*

# 设置默认时区
ENV TZ=Asia/Shanghai

# ...省略

假设通过上述 Dockerfile 构建的镜像名为 nginx:1.23-tz-shanghai。 通过 注入变量 修改时区。

直接使用, 我们将得到 CST 时区。

以下就不通过上述 Dockerfile 构建镜像了。 时区反着来。

默认 nginx:1.23 使用的是 Etc/UTC 时间。

1
2
$ docker run --rm nginx:1.23 date
Wed Dec 21 14:23:03 UTC 2022

在启动的时候, 注入上海时区的环境变量

1
2
$ docker run --rm -e "TZ=Asia/Shanghai" nginx:1.23 date
Wed Dec 21 22:23:30 CST 2022

docker-composeKubernetes 通过各自的方式注入环境变量即可。

时区列表

全球所有可用时区, 参考地址 https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List