Docker 时区调整方案

Posted Mr小三

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker 时区调整方案相关的知识,希望对你有一定的参考价值。

对于经常使用 Docker 的人来说,可能会碰到一个问题:时区问题。

大部分 Docker 镜像都是基于 Alpine,Ubuntu,Debian,CentOS 等基础镜像制作而成。

基本上都采用 UTC 时间,默认时区为零时区。

docker run --name test --rm -ti alpine /bin/sh
/ # date
Fri Nov 29 08:14:49 UTC 2019

而我们主要用的是 CST 时间,北京时间,位于东八区。时区代号: Asia/Shanghai

docker run --name test --rm -ti -v /etc/timezone:/etc/timezone:ro -v /etc/localtime:/etc/localtime:ro alpine /bin/sh
/ # date
Fri Nov 29 16:13:55 CST 201

对比一下,我们会发现,时间上相差 8 小时。

经过一系列探索实践,我们总结了一些 Docker 时区调整方案。

一、运行 Docker 容器时调整时区
在 Linux 系统中,控制时区和时间的主要是两个地方:

/etc/timezone 主要代表当前时区设置,一般链接指向/usr/share/zoneinfo目录下的具体时区。
/etc/localtime 主要代表当前时区设置下的本地时间。

  1. 通用 docker 时区修改方案
    宿主机为 Linux 系统
    当宿主机为 Linux 系统时,我们可以直接将宿主机上的/etc/timezone和/etc/localtime挂载到容器中,这样可以保持容器和宿主机时区和时间一致。
 -v /etc/timezone:/etc/timezone:ro -v /etc/localtime:/etc/localtime:ro

使用示例如下:

docker run --name test --rm -ti -v /etc/timezone:/etc/timezone:ro -v /etc/localtime:/etc/localtime:ro alpine /bin/sh
/ # date
Fri Nov 29 16:13:55 CST 2019
  1. 通过传递环境变量改变容器时区
    适用于基于 Debian 基础镜像, CentOS 基础镜像 制作的 Docker 镜像
    不适用于基于 Alpine 基础镜像, Ubuntu 基础镜像 制作的 Docker 镜像
    对于基于 Debian 基础镜像,CentOS 基础镜像制作的 Docker 镜像,在运行 Docker 容器时,传递环境变量-e TZ=Asia/Shanghai进去,能修改 docker 容器时区。
-e TZ=Asia/Shanghai

使用示例如下:

docker run --name test -e TZ=Asia/Shanghai --rm -ti debian /bin/bash
/# date
Fri Nov 29 18:46:18 CST 2019

二、制作 Docker 镜像时调整时区
通过编写 Dockerfile,构建自己的 Docker 镜像,可以永久解决时区问题。

  1. Alpine
    根据《Setting the timezone》提示,我们可以将以下代码添加到 Dockerfile 中:
ENV TZ Asia/Shanghai

RUN apk add tzdata && cp /usr/share/zoneinfo/$TZ /etc/localtime \\
    && echo $TZ > /etc/timezone \\
    && apk del tzdata
  1. Debian
    Debian 基础镜像 中已经安装了 tzdata 包,我们可以将以下代码添加到 Dockerfile 中:
ENV TZ=Asia/Shanghai \\
    DEBIAN_FRONTEND=noninteractive

RUN ln -fs /usr/share/zoneinfo/$TZ /etc/localtime \\
    && echo $TZ > /etc/timezone \\
    && dpkg-reconfigure --frontend noninteractive tzdata \\
    && rm -rf /var/lib/apt/lists/*
  1. Ubuntu
    Ubuntu 基础镜像中没有安装了 tzdata 包,因此我们需要先安装 tzdata 包。

我们可以将以下代码添加到 Dockerfile 中。

ENV TZ=Asia/Shanghai \\
    DEBIAN_FRONTEND=noninteractive

RUN apt update \\
    && apt install -y tzdata \\
    && ln -fs /usr/share/zoneinfo/$TZ /etc/localtime \\
    && echo $TZ > /etc/timezone \\
    && dpkg-reconfigure --frontend noninteractive tzdata \\
    && rm -rf /var/lib/apt/lists/*
  1. CentOS
    CentOS 基础镜像 中已经安装了 tzdata 包,我们可以将以下代码添加到 Dockerfile 中。
ENV TZ Asia/Shanghai

RUN ln -fs /usr/share/zoneinfo/$TZ /etc/localtime \\
    && echo $TZ > /etc/timezone

总结
时区问题是大问题。

时间没统一好,业务会乱套。

解决Docker容器时区不一致的问题

查看linux系统时区和docker容器时区

date -R                          //查看linux主机时间和时区
date exec [container] date -R    // 查看容器时间和时区

技术图片

2者的时间差了8个小时

 

解决方案

1、利用Dockerfile创建镜像时。在Dockerfile中加入

ENV TIME_ZONE=Asia/Shanghai 
RUN ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone

2、容器创建时。加入时区挂载选项:-v /etc/localtime:/etc/localtime。实例:

docker run -d -p 6379:6379 -v /etc/localtime:/etc/localtime --name test-redis redis

技术图片

 3、容器已启动时。

docker exec -it container /bin/bash // 进入交互模式,container为容器ID或名称,下同
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
docker restart container // 重启容器
docker exec container date -R // 查看时区

技术图片

 

以上均亲测试,良心保证,另外网上有搜到docker cp /etc/localtime [container]:/etc/localtime方法,但实际验证没成功,不知为何。

以上是关于Docker 时区调整方案的主要内容,如果未能解决你的问题,请参考以下文章

Docker时区timezone问题

Docker 修改时区

docker 下 alpine 镜像设置时区的有效办法

docker 下 alpine 镜像设置时区的有效办法

如何在 docker 上更改 postgreSQL 9.5 的时区?

Dockerpyresttest的dockerfile调整,增加时区