是否有可能在码头集装箱更换日期?

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

但是,当我试图更改容器内的日期时,我得到了错误:

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

这对多克来说是不可能的。Docker 使用与外部内核相同的时钟。您需要的是完全虚拟化,它模拟一台完整的 PC。

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

如果您使用的是 Python 或 Java 这样的高级语言,那么通常会有一些钩子,可以在其中模拟特定的系统时间进行测试,或者编写包装“从系统获取当前时间”并返回测试所需的代码。

特别是对于 Java,使用 joda-time,在这里您可以使用 DateTimeUtils.setCurrentMillis*()注入自己的时间源。

在不影响主机操作系统的情况下,动态更改 Docker 容器中的时间是非常可能的。

解决方案是伪造它。 这个自由主义者拦截所有用于检索当前时间和日期的系统调用程序。

这个实现很简单,可以在 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())

这招对我很管用,也许你可以试试:

重新配置 tzdata

编辑: 在有问题的容器中执行它。将出现一个接口。在那里,你可以编辑时区和本地时间,例如,并设置正确,这修复了我的问题,这是一样的。

祝你好运!

对我来说,我实际上需要设置测试的实际日期。我发现下面的选项可以在 Mac 上运行,但是你必须意识到你要改变所有容器的日期,因为你要改变 Docker 所有容器使用的底层 Alpine VM 的日期。

选项1: 更改主机的日期并重新启动码头

当:

  • 你可以重启码头。
  • 您可以更改主机的日期

步骤:

  1. 把你的箱子停下。
  2. 通过日期和时间首选项更改机器的日期
  3. 重启码头。
  4. 启动容器。

再次运行此序列以返回正确的日期和时间。

选项2: 更改高山 VM 的日期

当:

  • 你不能重启码头。
  • 您不能设置主机的日期

步骤:

    • 屏幕开始为空白,按几次回车键。
    • 你所有的码头集装箱现在将有你的新时间。你可以 也可以使用其他格式,查找关于“ busybox date”的文档 它与其他 约会实现不完全相同。
  1. 退出按 control-a :键并键入 d
    • 这将分离 screen 会话,但是让 tty 运行。

重置时间:

    • 这是你的案子。
    • 这将使用/etc/ntp.conf 中定义的服务器(这看起来像是回到主机时钟的神奇桥梁)
  1. 退出按 control-a :键并键入 quit
    • 这将终止您的 screen 和 tty 会话。

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

下面是一个使用它的例子,Java 使用 Groovy 作为一个例子,但是 Tomcat 也可以使用。

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

然后构建和传递 abc0环境变量,例如在码头运行时

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

资料来源: http://github.com/trajano/alpine-libfaketime rel = “ noReferrer”> trajano / 阿尔卑斯山-libfaketime | Github 和 docker 图片在 < a href = “ https://hub.docker.com/r/trajano/alpine-libfaketime”rel = “ noReferrer”> trajano/阿尔卑斯山-libfaketime | dockerhub

我还基于 Ubuntu 创建了一个变体: / Ubuntu-faketime | Github

我在 Jenkins Docker 实例中遇到了同样的问题,按照以下步骤解决了这个问题

  1. 进入集装箱

    Docker exec-it 9d41c699a8f4/bin/bash

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

  3. 使用 nano 设置新的时区: 亚洲/科伦坡(您的时区在这里)

  4. 重启容器

(执行到容器中)

rm /etc/localtime(见时区)

设定新时区

我的解决方案: 我运行 通过流浪者在一个虚拟机虚拟机上停靠

这没有听起来那么复杂。下面的 Vagrantfile在机器启动之前将 vm 的日期时间重置为特定的日期时间。相应的 docker-compose 提供程序负责自动运行 docker-compose.yml

流浪汉档案:

Vagrant.configure("2") do |config|
config.vm.define "ubuntuvm" do |ubuntuvm|
config.vm.box = "ubuntu/focal64"
config.vm.provision :docker


ubuntuvm.trigger.before :up do |trigger|
trigger.info = "changing time"
trigger.ruby do |env,machine|
require 'time'
machineTime = "2022/07/02 00:20:00"
offset = DateTime.parse(machineTime).strftime("%Q").to_i - DateTime.now.strftime("%Q").to_i
puts "Updating machine time to: #{machineTime} by shifting biossystemtime #{offset} ms"
puts `VBoxManage setextradata #{machine.id} "VBoxInternal/Devices/VMMDev/0/Config/GetHostTimeDisabled" 1`
puts `VBoxManage modifyvm #{machine.id} --biossystemtimeoffset #{offset}`
end
end
end




config.vm.hostname = "ubuntuvm"
# config.vm.network "forwarded_port", guest: 80 host: 8080
# config.vm.synched_folter "../data"", "/vagrant_data"


config.vm.provider "virtualbox" do |vb|
# vb.memory = "1024"
end
config.vm.provision :docker_compose, yml: "/vagrant/docker-compose.yml", rebuild: true, run: "always"
end

然后是 我只需要做以下几件事:

# start the machine and run the docker-compose
vagrant up

每次我打开机器,都会看到这样的信息:

ubuntuvm: Updating machine time to: 2022/07/02 00:20:00 by shifting biossystemtime -212710744 ms
ubuntuvm: Running docker-compose up...

其他指令:

# get inside the machine with ssh to check its time and also check the container's time (docker commands already exist inside there due to the provisioner).
vagrant ssh ubuntuvm
# stop the machine
vagrant halt
# destroy the machine
vagrant destroy

先决条件

已知问题:

仅在第一次运行时,vagrant up将无法更新时间,因为出于某种原因,甚至在创建机器之前就执行了 before-up 触发器。在所有其他执行中,机器已经在那里了,所以时间按预期重置。