修改单一容器时间

需求

客户提供的数据有时间限制,需要把数据制定到一个特定的时间点去测试,如何在 修改容器时间 而不影响 宿主机时间

宿主机操作系统:CentOS Linux release 7.7.1908 (Core)

实现逻辑

首先,运行容器尝试直接修改容器内时间,如下:

运行一个容器:
docker run -d -p 80:80 nginx:alpine
进入容器修改时间:
docker exec -it d0d1cc9d5 sh
/ # date -R
Fri, 25 Nov 2022 15:48:40 +0000
/ # date -s '2000-11-25 15:48:51'
date: can't set date: Operation not permitted
Fri Nov 25 15:48:51 UTC 2022

通过上面的操作,确认无法通过 date 命令来修改容器内时间。这是由于docker容器的隔离是基于Linux的Capability机制实现的,Linux的Capability 机制允许你将超级管理员相关的最高权限划分为不同的小单元。而要修改系统时间需要有 SYS_TIME 权限。使用 --cap-add--cap-drop 可以添加或禁止特定的权限。--privileged 参数也可以达到开放权限的作用,与 --cap-add 的区别就是,--privileged 是将所有权开放给容器。

docker 使用 --privileged , --cap-add--cap-drop 来对容器本身的能力进行开放或限制。

使用 --privileged 尝试修改时间:

docker run --name ngx -d -p 80:80 --privileged nginx:alpine
root@k8s-master(192.168.1.11)/root> docker exec -it ngx sh
/ # date
Fri Nov 25 15:57:09 UTC 2022
/ # date -s '2000-11-25 15:57:14'
Sat Nov 25 15:57:14 UTC 2000
/ # date -R
Sat, 25 Nov 2000 15:57:17 +0000

容器内时间修改成功,查看宿主机时间有没有被修改。

date
Sat Nov 25 23:58:19 CST 2000

可以发现, 一旦添加了 --privileged 容器就拥有了宿主机超级用户的权限,修改容器内时间连通宿主机时间一起修改了。

这种方式是不可取的,我们的需求仅仅是修改这一个容器的时间,而非宿主机的时间。如果该宿主机运行其他容器,则连同所有容器的时间都会发生变动。

libfaketime的使用

Github 有一个开源的 libfaketime 项目,就能解决仅修改一个容器的问题。

项目地址:https://github.com/wolfcw/libfaketime

安装过程

以 centos 镜像举例说明:

  1. dockerfile 如下
FROM centos:7
RUN yum install make gcc gcc-c++ git -y && \
    git clone https://github.com/wolfcw/libfaketime && \
    cd libfaketime/src && \
    make install
ENV LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1 \
    FAKETIME="2000-01-01 1:00:00"
ENTRYPOINT ["/usr/bin/python", "-m", "SimpleHTTPServer", "80"]
EXPOSE 80
  1. 构建镜像
docker build -t time:centos ./
  1. 运行为容器
docker run --name centos -d -p 80:80 time:centos

测试1 - 时间是否会递增

  1. 通过浏览器访问80端口,然后查看日志
> docker logs -f centos
192.168.199.10 - - [01/Jan/2000 01:00:00] "GET / HTTP/1.1" 200 -
192.168.199.10 - - [01/Jan/2000 01:00:00] code 404, message File not found
192.168.199.10 - - [01/Jan/2000 01:00:00] "GET /favicon.ico HTTP/1.1" 404 -
192.168.199.10 - - [01/Jan/2000 01:00:00] "GET / HTTP/1.1" 200 -
192.168.199.10 - - [01/Jan/2000 01:00:00] "GET / HTTP/1.1" 200 -
192.168.199.10 - - [01/Jan/2000 01:00:00] "GET / HTTP/1.1" 200 -

通过日志查看,发现 时间 是固定的,没有递增。

时间如何递增?

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

  1. 修改 dockerfile如下
FROM centos:7
RUN yum install make gcc gcc-c++ git -y && \
    git clone https://github.com/wolfcw/libfaketime && \
    cd libfaketime/src && \
    make install
ENV LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1 \
    FAKETIME="@2000-01-01 1:00:00"
ENTRYPOINT ["/usr/bin/python", "-m", "SimpleHTTPServer", "80"]
EXPOSE 80
  1. 构建镜像并启动为容器
docker build -t time:centos-v1 ./
docker run --name centos -d -p 80:80 time:centos-v1
  1. 访问并查看日志
> docker logs -f centos
192.168.199.10 - - [01/Jan/2000 01:00:10] "GET / HTTP/1.1" 200 -
192.168.199.10 - - [01/Jan/2000 01:00:20] "GET / HTTP/1.1" 200 -
192.168.199.10 - - [01/Jan/2000 01:00:22] "GET / HTTP/1.1" 200 -

通过观察日志验证了上面的说法,一个 @ 之差,需要注意!



--- EOF ---
posted @ 2022-11-25 18:17  hukey  阅读(1390)  评论(0编辑  收藏  举报