Docker容器时间和时区(不会反映更改)


135

Docker容器从哪里获取时间信息?我已经从基本的ubuntu:trusty映像创建了一些容器,当我运行它并请求“ date”时,我得到了UTC时间。

有一段时间我通过在Dockerfile中执行以下操作来解决此问题:

RUN sudo echo "America/Los_Angeles" > /etc/timezone

但是,由于某种原因而停止工作。在网上搜索时,我看到了以下建议:

docker run -v /etc/timezone:/etc/timezone [image-name]

这两种方法都可以正确设置时区!

$ cat /etc/timezone
America/Los_Angeles
$ date
Tue Apr 14 23:46:51 UTC 2015

有人知道会给什么吗?


3
如果你使用Alpine,你需要安装tzdata第一,看到这里github.com/gliderlabs/docker-alpine/issues/136
Belter

1
供参考。。。我希望将容器的时区设置为docker运行时,而不是docker build / dockerfile时。使用-v /etc/localtime:/etc/localtime:ro(CentOS)的作品。内部容器命令行日期以预期的时区格式返回日期。但是在容器中运行的詹金斯认为时区是UTC。为什么?/ etc / localtime是建立容器中../usr/share/zoneinfo/UTC的符号链接。容器中UTC文件的内容现在是新时区。但是jenkins(也许还有其他基于Java的软件)使用的符号链接的名称仍然是“ UTC”。寻找解决方案。。。
gaoithe

1
需要两件事:1.创建容器时,使用init脚本设置/ etc / localtime symlink和/ etc / timezone;以及2.对于jenkins时区是从两个Java选项中获取的,这些选项需要传递给init脚本,开始詹金斯进程。例如“ -Dorg.apache.commons.jelly.tags.fmt.timeZone = America / New_York -Duser.timezone = America / New_York”。抱歉,这是针对詹金斯的,但希望对其他詹金斯用户有用。
gaoithe

Answers:


208

此处的秘密在于,dpkg-reconfigure tzdata只需将文件创建/etc/localtime为副本,硬链接或符号链接(首选符号链接)即可/usr/share/zoneinfo。因此,可以完全从您的Dockerfile做到这一点。考虑:

ENV TZ=America/Los_Angeles
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

另外,TZ也可以在容器中正确设置。

这也是与发行版无关的,因此几乎可以在任何Linux上使用。

注意:如果您使用的是基于高山的映像,则必须安装第tzdata一个。(在此处查看此问题)

看起来像这样:

RUN apk add --no-cache tzdata
ENV TZ America/Los_Angeles


5
对于Ubuntu:16.04(可能还有其他版本),您需要tzdata安装软件包才能使其正常工作。
Opsse

5
我是唯一认为在Dockerfile中对时区进行硬编码不是很聪明的人吗?
沃尔夫冈

1
@Wolfgang这是一个示例。你可以在你通常会提供环境变量,在命令行中,搬运工,compose.yml等,如任何其他方式提供它
迈克尔·汉普顿

我注意到,至少对于基于Alpine的图像,仅设置TZ变量就足够了。我不必设置符号链接或其他任何东西。
code_dredd

58

通常,在docker容器中设置一个环境变量就足够了,就像这样:

docker run -e TZ=Europe/Amsterdam debian:jessie date

当然这也适用docker-compose


2
这似乎是最优雅的方式。请注意,某些基本映像(如ubuntu:16.04)没有tzdata应在Dockerfile中添加的软件包。
朱利安·法斯特(JulienFastré)'17

1
+1-我同意朱利安;这似乎是在运行时设置时区的最优雅的方法。这在CentOS上运作良好。Alpine映像确实需要安装'tzdata'软件包,在构建时优先于harcoding配置,除非无法容忍额外的3MB映像有效负载:)
Frelling

这似乎很好,但似乎对我不起作用(使用CentOS 7.5.1804和tzdata-2018e-3.el7.noarch)?悲伤的脸
gaoithe

22

挂载/etc/localtime在映像中,因此它是host -v最受欢迎的一种。

但请参阅问题12084

这是不正确的,因为当软件需要/etc/timezone设置文件时,它不起作用。
这样,您将其保留为默认值etc/UTC

我已经确定,实际上没有万无一失的优雅方法来在Docker容器内设置时区。
所以终于解决了这个问题:

应用dockerfile:

# Relocate the timezone file
RUN mkdir -p /config/etc && mv /etc/timezone /config/etc/ && ln -s /config/etc/timezone /etc/

应用程序入口点脚本:

# Set timezone as specified in /config/etc/timezone
dpkg-reconfigure -f noninteractive tzdata

数据量/configdockerfile,已本地化到特定国家或地区:

# Set the time zone
RUN echo "Europe/London" > /config/etc/timezone

...这并不优雅,因为涉及3个单独的文件,并/etc/localtime在每个运行时容器启动时重新创建。这相当浪费。

但是,它确实可以正常运行,并且成功实现了基本应用程序映像与每个按国家/地区本地化配置之间的分离。
在3行代码中。


1
对我来说,是: RUN echo "Europe/London" > /etc/timezone
jpmottin

@jpmottin那么在serverfault.com/a/856593/783中又是什么呢?
VonC

18

您可以在docker-container中将本地文件(/ etc / timezone和/ etc / localtime)添加为卷。

docker-compose.yml用以下几行更新您的内容。

volumes:
    - "/etc/timezone:/etc/timezone:ro"
    - "/etc/localtime:/etc/localtime:ro"

现在,容器时间与您的主机上的时间相同


如果您在CentOS分布式主机上,请echo "Europe/Paris" > /etc/timezone在重新启动容器之前输入命令。
CrazyMax

这可以在MacOS主机上使用吗?
Redsandro

在MAC中不起作用
Marcello de Sales

这曾经可以在MacOS上运行,但很长一段时间后我才再次尝试,得到了以下内容。不知道是High Sierra还是docker更改引起的:“ docker:来自守护程序的错误响应:挂载被拒绝:OS / OS不共享/ etc / localtime路径,并且Docker不知道。您可以从Docker配置共享路径- >首选项...->文件共享。有关更多信息,请参阅docs.docker.com/docker-for-mac/osxfs/#namespaces
gae123 '18

1
因为/ etc / localtime是一个符号链接,所以这将破坏您的zoneinfo数据库(因此/ usr / share / zoneinfo / Some / Thing可能会在容器内挂载为/ usr / share / zoneinfo / UTC)。更不用说您将主机中的db文件与容器中的db文件混合了。
ionelmc

12

在Ubuntu 16.04映像中有错误。解决方案是

    ENV TZ 'Europe/Tallinn'
    RUN echo $TZ > /etc/timezone && \
    apt-get update && apt-get install -y tzdata && \
    rm /etc/localtime && \
    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
    dpkg-reconfigure -f noninteractive tzdata && \
    apt-get clean

1
说真的...这是唯一有效的解决方案!
Gerrat

1
还必须这样做-默认情况下,似乎tzdata在某些发行版中不再存在。
彼得

4

如果您使用基于的docker image ubuntu

# Change the docker default timezone from UTC to SGT
echo "Asia/Singapore" > /etc/timezone
dpkg-reconfigure tzdata
date

3

感谢VonC提供信息并链接到该问题。这看起来像是一个混乱的混乱局面,因此我对如何解决此问题的想法进行了一些测试,并且效果很好。

>docker run -it ubuntu:trusty /bin/bash
#dpkg-reconfigure tzdata

(按照提示选择我的时区)

>docker commit [container-id] chocko/ubuntu:local

然后我更新了Dockerfile来反映这一点:

FROM chocko/ubuntu:local

这肯定有问题,因为它似乎太容易被忽视了……还是可以接受?


这也是我尝试过的方法,但是在我放置容器后,时区仍然会自行重置exit。这是在Debian上。
Mike Chamberlain

@MikeChamberlain您碰巧尝试了上述迈克尔·汉普顿的已接受答案吗?我还没有自己实现它,但是我认为这是考虑它收到的支持意见的方法。
Chockomonkey

2

在这里加两分钱,因为我已经尝试了其中的几分钱,但是在基于高山的图像上都没用。

但是,这可以解决问题:

ENV TZ=America/Toronto
RUN apk update
RUN apk upgrade
RUN apk add ca-certificates && update-ca-certificates
RUN apk add --update tzdata
RUN rm -rf /var/cache/apk/*

[ 来源 ]


1

docker run参数中设置时区的更通用的方法:

-e TZ=`ls -la /etc/localtime | cut -d/ -f8-9`

或重用:

function GET_TZ () {
    ls -la /etc/localtime | cut -d/ -f8-9
}

...
-e TZ=`GET_TZ`

如果您的基本映像是alpine(5MB)且未安装“ tzdata”
无济于事
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.