Search code examples
dockerdatedockerfileddev

How can I temporarily change the time in my ddev web container (faketime, libfaketime)


I’m trying to debug something that happens a few days after another event, and would like to speed up the test without circumventing the date delay related code. Is there anyway to change the date in the ddev containers temporarily?


Solution

  • Thanks to help from this question and kind support from @rfay. I came up with this solution using the libfaketime

    I created .ddev/web-build/Dockerfile with the following content:

    ARG BASE_IMAGE
    FROM $BASE_IMAGE
    RUN apt-get update && apt-get install -y make build-essential
    WORKDIR /
    RUN git clone https://github.com/wolfcw/libfaketime.git
    WORKDIR /libfaketime/src
    RUN make install
    

    I ran ddev start to make sure the container would still build.

    Then added a command at .ddev/commands/host/faketime:

    #!/bin/bash
    
    ## Description: Enable or disable faketime
    ## Usage: faketime on YYYY-mm-dd|off|status
    ## Example: "ddev faketime on 2020-05-04", "ddev faketime off", "ddev faketime status"
    
    if [ $# -eq 0 ] ; then
     echo "usage faketime YYYY-mm-dd or faketime off"
    fi
    
    case $1 in
        on|true|enable)
        echo $1
        echo $2
        echo "turning on"
          if date -j -f "%Y-%m-%d" -j ${2} > /dev/null 2>&1
          then
            echo "time set to ${2} 11:00:00, restarting..."
          ddev config --web-environment=LD_PRELOAD="/usr/local/lib/faketime/libfaketime.so.1",FAKETIME="${2} 11:00:00" && ddev start
        else
          echo "faketime on usage:  ddev faketime on YYYY-MM-DD"
        fi
        ;;
        off|false|disable)
          echo "turning faketime off"
          ddev config --web-environment=LD_PRELOAD="" && ddev start
        ;;
        status)
          if grep -q 'FAKETIME' ${DDEV_APPROOT}/.ddev/config.yaml;
          then
            echo "faketime is on."
            ddev exec date +%F
          else
            echo "faketime is off."
            ddev exec date +%F
          fi
        ;;
      *)
        echo "invalid argument"
        ;;
    esac
    

    On a Mac, this allows me to run ddev faketime on 2020-05-4 to set the container date to May 4th, 2020, and ddev faketime off to turn it back off. On a unix based system, the date validation part of the script would need to be different.

    if date -j -f "%Y-%m-%d" -j ${2} > /dev/null 2>&1;

    would need to be something like

    if date "+%Y-%m-%d" -d ${2} 2>&1;

    faketime off and faketime on will both cause the containers to restart, while faketime status will just read whether the time is being faked and report the current container date.

    For my purposes, setting the time to 11 AM was fine. I just cared about the date itself. For your application you may want to change the arguments and specify time as well.