因为开发需要一个定时的任务场景进行测试,然后我们的环境也是运行在 docker 里面,所以需要改一下我们测试环境中的 docker 时间。经过查询了解,主要是如下两种方式

添加 --cap-add SYS_TIME 参数

第一种是通过在 docker 启动的时候添加 --cap-add SYS_TIME 参数启动容器后,在 docker 容器里可以直接使用 date 命令修改容器中的时间,但这样宿主机的时间也会修改,因为 docker 容器是轻量级的,docker 容器时间和宿主机都是共享 linux 内核并不是独立的。所以不适应我们的测试场景。

# docker run -it --cap-add SYS_TIME --name test01 -d node:12.14

编译安装 libfaketime

另一种方式则是 docker 镜像编译安装 libfaketime,然后使用 LD_PRELOAD 这个环境变量使 date 连接这个项目编译的库来“欺骗”应用,达到修改 docker 容器时间的修改,而且不会影响到宿主机的时间。 libfaketime 具体信息请在 gitlab 中查询。这里使用一个测试的 docker 镜像安装 libfaketime,重新 build 成一个新的 docker 镜像,利用此镜像启用 docker 容器进行时间更改的测试。 Dockerfile 文件:

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

执行 build 进行构建新的 docker 镜像:

# docker build -t node-socket-faketime:12.14 .

使用新的镜像启动一个测试的 docker 容器来验证一下时间修改:

# docker run --name test01 -e LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1 -e FAKETIME="2000-01-01 10:30:00" -d node-socket-faketime:12.14 bash -c  "while true;do sleep 2;done"

进入 docker 中查看时间:

# docker exec -it test01 bash
root@4608002ab568:/libfaketime/src# date
Sat Jan  1 10:30:00 UTC 2000
root@4608002ab568:/libfaketime/src# python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
127.0.0.1 - - [01/Jan/2000 10:30:00] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [01/Jan/2000 10:30:00] "GET / HTTP/1.1" 200 -

可以看到时间修改已经生效了,是一个指定的过去时间,但是这个时间一直不变,所以需要修改一下 FAKETIME 的变量方式,我们直接在刚才创建已经有的 test01 这个容器里直接修改一下 FAKETIME 变量,具体的执行步骤如下:

# docker exec -it test01 bash
root@4608002ab568:/libfaketime/src# date 
Sat Jan  1 10:30:00 UTC 2000
root@4608002ab568:/libfaketime/src# export FAKETIME_DONT_RESET=1 
root@4608002ab568:/libfaketime/src# export FAKETIME="@2000-01-01 10:30:00"
root@4608002ab568:/libfaketime/src# date
Sat Jan  1 10:30:58 UTC 2000
root@4608002ab568:/libfaketime/src# python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
127.0.0.1 - - [01/Jan/2000 10:31:08] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [01/Jan/2000 10:31:10] "GET / HTTP/1.1" 200 -

注:FAKETIME="2000-01-01 10:30:00" 该变量设置后时间会一直保持不变,而 FAKETIME="@2000-01-01 10:30:00" 变量设置后时间会从这个时间往后递增。

通过上面的日志打印以及 date 命令输出结果,可以看到,通过 libfaketime 来修改 docker 容器时间是可以的,至少能满足我们的测试使用。