前言

如果在启动 Docker 容器的过程中没有单独配置 localtime,很可能造成 Docker 容器时间与主机时间不一致的情况,比如 UTC 和 CST 相差 8 小时,换句话来说就是容器时间与北京时间相差 8 个小时。

更新历史

2020 年 08 月 13 日 - 初稿

阅读原文 - https://liaojiaxin158.github.io/post/docker-localtime/


问题描述

问题:容器时间与北京时间相差 8 个小时

1
2
3
4
5
6
7
8
# 查看主机时间 
[root@localhost ~]# date
2020 年 07 月 27 日 星期三 22:42:44 CST

# 查看容器时间
# docker exec -it <containerid> /bin/sh
root@b43340ecf5ef:/# date
Wed Jul 27 14:43:31 UTC 2020

原因:宿主机设置了时区,而 Docker 容器并没有设置,导致两者相差 8 小时

可以发现,他们相隔了 8 小时

CST 应该是指(China Shanghai Time,东八区时间)
UTC 应该是指(Coordinated Universal Time,标准时间)
所以,这 2 个时间实际上应该相差 8 个小时

所以,必须统一两者的时区

解决方案

docker run 添加时间参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-v /etc/localtime:/etc/localtime

# 实例 1
docker run -p 3306:3306 --name mysql -v /etc/localtime:/etc/localtime

# 实例 2
docker run \
--detach \
--restart always \
--name 'scribe' \
--publish 11315:11315 \
--mount type=bind,source=/data/gop/,destination=/data/gop/,consistency=consistent \
-v /etc/localtime:/etc/localtime \
liaojiaxin/facebook-scribe

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
# 方法 1
# 添加时区环境变量,亚洲,上海
ENV TimeZone=Asia/Shanghai
# 使用软连接,并且将时区配置覆盖 / etc/timezone
RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone

# 方法 2
# CentOS
RUN echo "Asia/shanghai" > /etc/timezone
# Ubuntu
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

docker-compose

1
2
3
4
5
6
7
8
9
10
11
12
13
# 第一种方式 (推荐):
environment:
TZ: Asia/Shanghai

# 第二种方式:
environment:
SET_CONTAINER_TIMEZONE=true
CONTAINER_TIMEZONE=Asia/Shanghai

# 第三种方式:
volumes:
- /etc/timezone:/etc/timezone
- /etc/localtime:/etc/localtime

宿主机直接执行命令给某个容器同步时间

1
2
3
4
5
6
# 方法 1:直接在宿主机操作 
docker cp /etc/localtime 【容器 ID 或者 NAME】:/etc/localtime
docker cp -L /usr/share/zoneinfo/Asia/Shanghai 【容器 ID 或者 NAME】:/etc/localtime

# 方法 2:登录容器同步时区 timezone
ln -sf /usr/share/zoneinfo/Asia/Singapore /etc/localtime

在完成后,再通过 date 命令进行查看当前时间
但是,在容器中运行的程序的时间不一定能更新过来,比如在容器运行的 mysql 服务,在更新时间后,通过 sql 查看 mysql 的时间

select now() from dual;

可以发现,时间并没有更改过来
这时候必须要重启 mysql 服务或者重启 docker 容器,mysql 才能读取到更改过后的时间

文章目录
  1. 1. 前言
  2. 2. 更新历史
  3. 3. 问题描述
  4. 4. 解决方案
    1. 4.1. docker run 添加时间参数
    2. 4.2. Dockerfile
    3. 4.3. docker-compose
    4. 4.4. 宿主机直接执行命令给某个容器同步时间