背景:
测试想单独更改某个服务的时间进行测试流程,需要修改容器时间的同时不影响到宿主机的时间
修改容器时间的方法
使用 date 命令临时修改
[root@data-charge-server-67bfb86784-kt2t2 /]# date -s "2025-11-01 12:00:00"
date: cannot set date: Operation not permitted
Sat Nov 1 12:00:00 CST 2025使用 –privileged 和 –cap-add SYS_TIME
如果容器以特权模式运行,或者添加了SYS_TIME能力,可以在容器内部修改时间,但是会影响宿主机的时间。docker run --privileged --cap-add SYS_TIME -it ubuntu /bin/bash
date -s "2025-11-01 12:00:00"
#⚠️注意:这种方法会修改宿主机的时间,通常不推荐在生产环境中使用。使用 libfaketime(推荐用于测试)
libfaketime 是一个库,可以拦截系统调用,让应用程序看到虚假的时间,而不会真正修改系统时间。这种方法适合用于测试。yum install -y epel-release
yum install -y faketime
export LD_PRELOAD=/usr/lib64/faketime/libfaketime.so.1
export FAKETIME="2025-11-01 12:00:00"验证是否成功
[root@data-charge-server-67bfb86784-kt2t2 /]# date
Sat Nov 1 12:00:00 CST 2025若想要恢复,直接把环境变量修改为空即可
export LD_PRELOAD=
直接在容器内修改服务不生效,把faketime打包到服务的镜像内,以下是对应的dockerfile
FROM centos:7-sjdk8-v1
ADD /data-charge-server/target/data-charge-server-0.0.1-SNAPSHOT.jar data-charge-server-0.0.1-SNAPSHOT.jar
ENV TZ=Asia/Shanghai
ENV LANG en_US.UTF-8
ENTRYPOINT exec java ${JAVA_OPTS} -jar data-charge-server-0.0.1-SNAPSHOT.jar
#改为
FROM centos:7-sjdk8-v1
RUN yum install -y epel-release
RUN yum install -y faketime
ADD /data-charge-server/target/data-charge-server-0.0.1-SNAPSHOT.jar data-charge-server-0.0.1-SNAPSHOT.jar
ENV TZ=Asia/Shanghai
ENV LANG en_US.UTF-8
ENTRYPOINT ["faketime", "2025-11-01 12:00:00", "sh", "-c", "exec java $JAVA_OPTS -jar data-charge-server-0.0.1-SNAPSHOT.jar"]踩坑一:实际测试后虽然容器命令行内生效,但是服务无法读取到
Kimi:
faketime 只能对「动态链接」的 glibc 程序生效,而官方 OpenJDK 镜像(openjdk:8/11/17…)为了体积和兼容性,把 java 做成了静态链接的 musl 版本(Alpine)或静态 glibc 版本踩坑二:把FAKETIME打到服务的镜像内,环境变量的LD_PRELOAD和FAKETIME加到dockefile中会导致服务无法启动,所以去除环境变量
Kimi:
JVM 对 LD_PRELOAD 非常敏感,尤其是涉及时间函数(如 clock_gettime、gettimeofday)时,faketime 会导致 JVM 崩溃或卡住,表现为:- 容器启动后无日志
- java 进程不存在
- docker logs 无输出