背景:

测试想单独更改某个服务的时间进行测试流程,需要修改容器时间的同时不影响到宿主机的时间

修改容器时间的方法

  1. 使用 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"
    #⚠️注意:这种方法会修改宿主机的时间,通常不推荐在生产环境中使用。
  2. 使用 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 无输出