V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wsgzao
V2EX  ›  程序员

Docker 容器时间如何与宿主机同步问题解决方案小结

  •  
  •   wsgzao ·
    wsgzao · 2020-08-14 15:04:20 +08:00 · 2235 次点击
    这是一个创建于 1322 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

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

    更新历史

    2020 年 08 月 13 日 - 初稿

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


    问题描述

    问题:容器时间与北京时间相差 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 添加时间参数

    -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 \
        wsgzao/facebook-scribe
    
    

    Dockerfile

    # 方法 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

    #第一种方式(推荐):
    environment:
      TZ: Asia/Shanghai
      
    #第二种方式:
    environment:
      SET_CONTAINER_TIMEZONE=true
      CONTAINER_TIMEZONE=Asia/Shanghai
    
    #第三种方式:
    volumes:
      - /etc/timezone:/etc/timezone
      - /etc/localtime:/etc/localtime
    
    

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

    # 方法 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 才能读取到更改过后的时间

    9 条回复    2020-08-16 15:31:28 +08:00
    iyaozhen
        1
    iyaozhen  
       2020-08-14 15:12:32 +08:00
    额 时间是时间,时区是时区
    binux
        2
    binux  
       2020-08-14 15:16:40 +08:00 via Android
    用 docker 就是想要运行环境隔离,你还非要和主机同步。。
    asilin
        3
    asilin  
       2020-08-14 15:31:27 +08:00
    时间是时间,时区是时区

    除了最新的内核支持时间命名空间之外,基本上主流发行版的容器时间都是和主机共用。
    wsgzao
        4
    wsgzao  
    OP
       2020-08-14 15:35:22 +08:00
    @iyaozhen #1

    @asilin #3

    感谢纠正描述错误,应该是时区同步而非时间
    szkoda
        5
    szkoda  
       2020-08-15 09:40:12 +08:00
    你是去了坡县的那位老哥?
    wsgzao
        6
    wsgzao  
    OP
       2020-08-16 00:01:07 +08:00
    @szkoda #5 是的
    saytesnake
        7
    saytesnake  
       2020-08-16 00:09:07 +08:00
    这个一般是在 Dockerfile 层面处理吧? alpine 的就要装个 tzdata 。不过 Debian 派系基础镜像的只需 run 环节定义 TZ 变量即可。
    mkdir
        8
    mkdir  
       2020-08-16 00:58:33 +08:00 via iPhone
    @saytesnake 请教,通常在构建镜像的时候中途装软件下载速度太慢怎么解决?
    saytesnake
        9
    saytesnake  
       2020-08-16 15:31:28 +08:00   ❤️ 1
    @mkdir 系统层面的软件改国内源,外部软件的话直接自行下载好然后在 Dockerfile ADD 或 COPY 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   947 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 21:07 · PVG 05:07 · LAX 14:07 · JFK 17:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.