2min.

How to fake time in a MySQL Container

Sometimes, you may want to fake the time in your test suite to ensure your code behaves well in all situations.

There is a famous library called libfaketime that allows you to set a specific time for a program. This library leverages the LD_PRELOAD environment variable. This variable allows anyone to prepend a new library before the regular ones. So basically, when you run your program, at some point it’ll call some system functions (syscall) or regular functions from different libraries, then you can replace them with your custom implementation. For example, the library will replace calls like gettimeofday or time.

Section intitulée how-to-use-libfaketime-with-a-mysql-containerHow to use libfaketime with a MySQL Container ?

Section intitulée installationInstallation

You’ll need to build a special image, with the library installed. For example, we’ll use the mysql:8 image. Since there are no build tools, nor package manager available in the image, we’ll use the “builder pattern”.

FROM ubuntu:18.10 as builder

RUN sed -i 's#http://archive.ubuntu.com#http://old-releases.ubuntu.com#' /etc/apt/sources.list \
    && apt update \
    ; apt install -y \
        build-essential \
        git

RUN git clone https://github.com/wolfcw/libfaketime.git /tmp/libfaketime \
    && cd /tmp/libfaketime \
    && make \
    && make install

FROM mysql:8

COPY --from=builder /usr/local/lib/faketime/libfaketime.so.1 /usr/local/lib/
COPY --from=builder /usr/local/lib/faketime/libfaketimeMT.so.1 /usr/local/lib/

The builder and the runtime (mysql:8) must use the very same glibc, that’s why we are using Ubuntu 18.10. And since it’s an EOLed distribution, we need to hack the image a bit :/

Anyway, for all MySQL distributions, you must compile and install the library.

Finally, build the image:

docker build -t test-mysql-faketime .

Section intitulée configuration-and-usageConfiguration and usage

Now, we have to start the container, with some extra environment variables:

  • LD_PRELOAD=/usr/local/lib/libfaketime.so.1 : Loads the library;
  • FAKETIME="-15d" : Sets the date you want.
docker run --rm -u root -it \
    -e MYSQL_ROOT_PASSWORD=p \
    -e LD_PRELOAD=/usr/local/lib/libfaketime.so.1 \
    -e FAKETIME="@2022-02-22 22:22:22" \
    test-mysql-faketime

Finally, you can query the container, to ensure everything work as expected:

docker exec -it cranky_panini mysql -uroot -pp -e "SELECT NOW()"
mysql: [Warning] Using a password on the command line interface can be insecure.
+---------------------+
| NOW()               |
+---------------------+
| 2022-02-22 22:22:22 |
+---------------------+

Section intitulée conclusionConclusion

Using libfaketime is quite easy. The hardest part is to compile it for your distribution. But honestly, the library has very few dependencies, so it’s not a big deal.

This technique works not only for MySQL but for everything (Redis, Postgres, Nginx, Goland, PHP, etc).

Finally, you may want to add a special container with a hardcoded date in your docker-compose.yml or you can run a container each time you need. It’s up to you.

Commentaires et discussions

Ces clients ont profité de notre expertise