是否可以在docker容器中更改日期?

时间:2015-04-10 08:35:43

标签: tomcat docker

我有一个在tomcat中运行程序的容器。我只需要在此容器中更改日期并测试我的程序行为。我有时间敏感的逻辑,有时需要看看几天或几个月后会发生什么。 在码头工具中有可能吗?我读到如果我在容器中更改日期,日期将在主机系统上更改。但对我来说这是一个坏主意。我需要在一台服务器上安装这个应用程序的几个实例,并且可以为每个实例设置不同的时间。

但是当我尝试更改容器内的日期时,我收到错误:

sudo date 04101812
date: cannot set date: Operation not permitted
Fri Apr 10 18:12:00 UTC 2015

8 个答案:

答案 0 :(得分:27)

可以动态更改Docker容器中的时间,而不会影响主机操作系统。

解决方案是伪造它。 This lib拦截所有系统调用程序用于检索当前时间和日期。

实施很容易。根据需要为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]

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

示例:

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

答案 1 :(得分:11)

Docker无法做到这一点。 Docker使用与外部内核相同的时钟。您需要的是完全虚拟化,它可以模拟完整的PC。

sudo失败,因为它只会使您root容器内的虚拟环境。此用户与主机系统的真实root无关(除了名称和UID),并且它无法执行真正的root可以执行的操作。

在使用像Python或Java这样的高级语言时,通常可以使用钩子来模拟测试的某个系统时间,或者编写包含“从系统获取当前时间”并返回测试所需内容的代码。

专门针对Java,请使用joda-time。在那里,您可以使用DateTimeUtils.setCurrentMillis*()注入自己的时间源。

答案 2 :(得分:5)

这对我有用,也许你可以尝试一下:

  

dpkg-reconfigure tzdata

编辑:在有问题的容器内执行它。将出现一个界面。例如,您可以编辑时区和本地时间,并正确设置,解决了我的问题,这与您的问题相同。

祝你好运!

答案 3 :(得分:2)

对我来说,我实际上需要设置测试的实际日期。我发现以下选项适用于Mac,但您必须意识到您将更改所有容器的日期,因为您正在更改Docker用于其所有容器的基础Alpine VM的日期。

选项1:更改主机的日期&重启docker

在以下时间使用:

  • 您可以重启docker。
  • 您可以更改主机的日期

步骤:

  1. 停止容器。
  2. 通过日期和时间更改机器的日期。时间偏好
  3. 重启docker。
  4. 启动容器。
  5. 再次运行此序列以返回正确的日期&时间。

    选项2:更改Alpine VM的日期

    在以下时间使用:

    • 您无法重启docker。
    • 您无法设置主机的日期

    步骤:

    1. screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty
      • 屏幕开始空白,点击输入几次。
    2. date -s [hh:mm]
      • 您的所有docker容器现在都将拥有您的新时间。您可以 也使用其他格式,在“busybox date”上查找文档 它与其他 date 实现并不完全相同。
    3. 退出点击control-a :并输入d
      • 这会分离屏幕会话,但会让tty继续运行。
    4. 重置时间:

      1. screen -r
        • 这将恢复你的tty。
      2. ntpd -q
        • 这使用/etc/ntp.conf中定义的服务器(这看起来像是回到主机时钟的魔桥)。
      3. 退出点击control-a :并输入quit
        • 这会终止您的屏幕和tty会话。

答案 4 :(得分:2)

我创建了一个包含libfaketime的Docker映像,供Alpine使用,但是该过程可以在其他发行版中完成。

这里是使用Groovy作为示例的Java使用示例。但是也可以使用Tomcat。

FROM groovy:alpine
COPY --from=trajano/alpine-libfaketime  /faketime.so /lib/faketime.so
ENV LD_PRELOAD=/lib/faketime.so \
    DONT_FAKE_MONOTONIC=1

然后例如在执行docker run时构建并传递FAKETIME环境变量

docker build -f fakedemo-java.Dockerfile . -t fakedemo
docker run --rm -e FAKETIME=+15d fakedemo groovy -e "print new Date();"

源位于https://github.com/trajano/alpine-libfaketime中,泊坞窗映像位于https://hub.docker.com/r/trajano/alpine-libfaketime

我还基于Ubuntu https://github.com/trajano/ubuntu-faketime

创建了它的变体

答案 5 :(得分:0)

按照步骤修复我的问题后,我的jenkins docker实例遇到了相同的问题

  1. exec进入容器

    docker exec -it 9d41c699a8f4 / bin / bash

  2. 查看时区 cat /etc/timezone :输出Etc / UTC

  3. 使用nano设置新的时区:亚洲/科伦坡(此处是您的时区)

  4. 重新启动容器

答案 6 :(得分:0)

docker exec -it [Container Id] /bin/bash(执行到容器中)

rm /etc/localtime(查看时区)

ln -s /usr/share/zoneinfo/Asia/Karachi /etc/localtime(设置新时区)

答案 7 :(得分:-6)

是的,我测试过它并且有效!

运行图片时使用--privileged

示例:

docker run -i -t --rm --privileged my_image /bin/bash