如何在Docker容器中动态设置系统时间


28

有什么方法可以在不影响主机的情况下(在运行时)动态设置Docker容器系统时间?

使用

hwclock --set --date "Sat Aug 17 08:31:24 PDT 2016"

给出以下错误:

hwclock: Cannot access the Hardware Clock via any known method.
hwclock: Use the --debug option to see the details of our search for an access method.

使用

date -s "2 OCT 2006 18:00:00"

给出以下错误:

date: cannot set date: Operation not permitted

用例:

我需要测试对时间敏感的软件(行为取决于日期)。

其他常见用例:

  • 运行带有y2k错误的旧版软件
  • 符合2038年标准的测试软件
  • 调试与时间相关的问题,例如过期的SSL证书
  • 正在停止在特定时间范围内运行的软件
  • 确定性的构建过程。

这样做的目的是什么?您的用例是什么?
dawud

请参阅编辑。
Vingtoft


1
实际上,我只是使用libfaketime github.com/wolfcw/libfaketime找到并积极测试了一个解决方案,我将在不久后通过一个答案+工作示例进行更新。
Vingtoft

Answers:


21

有可能的

解决方案是在容器中伪造它。该库拦截所有用于检索当前时间和日期的系统调用程序。

实施很容易。根据需要向Dockerfile添加功能:

WORKDIR /
RUN git clone https://github.com/wolfcw/libfaketime.git
WORKDIR /libfaketime/src
RUN make install

切记设置环境变量 LD_PRELOAD在运行要应用伪造时间的应用程序之前。

例:

CMD ["/bin/sh", "-c", "LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1 FAKETIME_NO_CACHE=1 python /srv/intercept/manage.py runserver 0.0.0.0:3000]

现在,您可以动态更改服务器时间:

例:

import os
def set_time(request):
    print(datetime.today())
    os.environ["FAKETIME"] = "2020-01-01"  # Note: time of type string must be in the format "YYYY-MM-DD hh:mm:ss" or "+15d"
    print(datetime.today())

6
对于其他使用此解决方案的人,请注意,这不适用于golang应用程序或其他静态链接的exe。
Sentinel

5
谢谢@Sentinel。有趣的是,我刚刚通过google找到了这个答案,我特别想在golang应用程序中使用它,而且我注意到您仅在2个小时前对一个有1.5年历史的问题发表了评论。感觉就像是给我的。谢谢!:)
dimonomid '18年

为什么在您的情况下不起作用?Golang是否不使用系统调用来获取时间?@dimonomid我建议您尝试一下,可以快速实施该解决方案。
Vingtoft

1
@Vingtoft让我知道它是否确实有效,但是请四处搜索。Golang不会在库中动态链接。
Sentinel

1
@dimonomid是的,我很失望。实际上,对Docker更加失望。我需要实施与计时相关的测试。这使得Docker作为“容器”几乎毫无用处。我以为拦截时区同步的系统时间调用将是Docker议程上的第1项。显然不是。
Sentinel

4

Jenny D是正确的,因为默认情况下Docker容器不允许访问系统时钟。

但是,在Linux上,如果您的容器可以使用此功能,可以在创建容器时使用“ docker run”命令的“ --cap-add = SYS_TIME”选项来允许此功能:

# docker run --cap-add=SYS_TIME -d --name teamcity-server-instance -v /opt/teamcity/data:/data/teamcity_server/datadir -v /opt/teamcity/logs:/opt/teamcity/logs -p 80:8111 jetbrains/teamcity-server

然后,您可以从正在运行的容器内部更改时间:

# docker exec -it teamcity-server-instance /bin/bash
# date +%T -s "15:03:00"
15:03:00
#

参考文档:https : //docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities


2
这会更改主机上的时间。Linux系统上的时间当前未命名空间,主机和所有容器只有一个值。
BMitch

你是对的。这将更改主机时钟的时间。只需重新阅读该问题并意识到这个问题,就确实提到了关于不更改主机时钟的问题。我的立场是正确的:)
Oleg Kazakov

0

使用其他环境变量启动容器:

docker run -e "SET_CONTAINER_TIMEZONE=true" \
           -e "CONTAINER_TIMEZONE=US/Arizona" [docker image name]

我正在寻找一种动态设置时间的方法,这意味着可以在运行时设置时间。我已经更新了我的问题。
Vingtoft

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.