修改单一容器时间
需求
客户提供的数据有时间限制,需要把数据制定到一个特定的时间点去测试,如何在 修改容器时间 而不影响 宿主机时间 ?
宿主机操作系统: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
项目,就能解决仅修改一个容器的问题。
安装过程
以 centos 镜像举例说明:
- 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
- 构建镜像
docker build -t time:centos ./
- 运行为容器
docker run --name centos -d -p 80:80 time:centos
测试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" 变量设置后时间会从这个时间往后递增。
- 修改 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
- 构建镜像并启动为容器
docker build -t time:centos-v1 ./
docker run --name centos -d -p 80:80 time:centos-v1
- 访问并查看日志
> 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 -
通过观察日志验证了上面的说法,一个 @
之差,需要注意!