Comment définir l'heure système dynamiquement dans un conteneur Docker

28

Existe-t-il un moyen de définir l'heure système d'un conteneur Docker de manière dynamique (au moment de l'exécution) sans affecter la machine hôte?

En utilisant

hwclock --set --date "Sat Aug 17 08:31:24 PDT 2016"

donne l'erreur suivante:

hwclock: Cannot access the Hardware Clock via any known method.
hwclock: Use the --debug option to see the details of our search for an access method.

En utilisant

date -s "2 OCT 2006 18:00:00"

donne l'erreur suivante:

date: cannot set date: Operation not permitted

Cas d'utilisation:

J'ai besoin de tester un logiciel sensible au temps (le comportement dépend de la date).

Autres cas d'utilisation courants:

  • exécution d'un logiciel hérité avec des bogues y2k
  • test des logiciels pour la conformité à l'année 2038
  • débogage des problèmes liés au temps, tels que les certificats SSL expirés
  • exécuter un logiciel qui cesse de fonctionner en dehors d'un certain délai
  • processus de construction déterministes.
Vingtoft
la source
Quel serait le but de le faire? quel est votre cas d'utilisation?
dawud
Veuillez voir modifier.
Vingtoft
1
En fait, je viens de trouver et de tester positivement une solution en utilisant libfaketime github.com/wolfcw/libfaketime que je mettrai à jour avec une réponse + un exemple de travail sous peu.
Vingtoft

Réponses:

21

C'est possible

La solution est de le truquer dans le récipient. Cette bibliothèque intercepte tous les programmes d'appels système utilisés pour récupérer l'heure et la date actuelles.

La mise en œuvre est simple. Ajoutez des fonctionnalités à votre Dockerfile, le cas échéant:

WORKDIR /
RUN git clone https://github.com/wolfcw/libfaketime.git
WORKDIR /libfaketime/src
RUN make install

N'oubliez pas de définir les variables d'environnement LD_PRELOADavant d'exécuter l'application à laquelle vous voulez appliquer le temps factice.

Exemple:

CMD ["/bin/sh", "-c", "LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1 FAKETIME_NO_CACHE=1 python /srv/intercept/manage.py runserver 0.0.0.0:3000]

Vous pouvez maintenant modifier dynamiquement l'heure des serveurs:

Exemple:

import os
def set_time(request):
    print(datetime.today())
    os.environ["FAKETIME"] = "2020-01-01"  # Note: time of type string must be in the format "YYYY-MM-DD hh:mm:ss" or "+15d"
    print(datetime.today())
Vingtoft
la source
6
Pour les autres utilisateurs de cette solution, sachez que cela ne fonctionnera pas pour les applications golang ou d'autres exes liés statiquement.
Sentinel
5
Merci @Sentinel. Curieusement, je viens de trouver cette réponse via google, je veux spécifiquement l'utiliser avec une application golang, et j'ai remarqué que vous avez laissé ce commentaire sur une question de 1,5 ans il y a seulement 2 heures. C'est comme si c'était pour moi. Merci! :)
dimonomide
Pourquoi ne fonctionne pas dans votre situation? Golang n'utilise-t-il pas les appels système pour récupérer du temps? @dimonomid Je vous suggère de l'essayer, la mise en œuvre de la solution est rapide.
Vingtoft
1
@Vingtoft Faites-moi savoir si cela fonctionne, mais recherchez autour. Golang ne lie pas dynamiquement dans les bibliothèques.
Sentinel
1
@dimonomid Oui, j'ai été assez déçu. Plus déçu par Docker en fait. J'ai besoin d'implémenter des tests liés au timing. Cela rend Docker pratiquement inutile en tant que "conteneur". J'aurais pensé que l'interception des appels horaires du système pour la synchronisation du fuseau horaire aurait été le point 1 à l'ordre du jour de Docker. Apparemment non.
Sentinel
4

Jenny D a raison, car par défaut, le conteneur Docker ne permet pas d'accéder à l'horloge système.

Cependant, sous Linux, si votre conteneur a accès à cette capacité, vous pouvez autoriser cette capacité en utilisant l'option "--cap-add = SYS_TIME" de la commande "docker run" lors de la création de votre conteneur:

# docker run --cap-add=SYS_TIME -d --name teamcity-server-instance -v /opt/teamcity/data:/data/teamcity_server/datadir -v /opt/teamcity/logs:/opt/teamcity/logs -p 80:8111 jetbrains/teamcity-server

Ensuite, vous pouvez modifier l'heure depuis l'intérieur du conteneur en cours d'exécution:

# docker exec -it teamcity-server-instance /bin/bash
# date +%T -s "15:03:00"
15:03:00
#

Documentation de référence: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

Oleg Kazakov
la source
2
Cela modifie l'heure sur la machine hôte. Le temps sur un système Linux n'est pas actuellement à espace de noms, il n'y a qu'une seule valeur pour l'hôte et tous les conteneurs.
BMitch
Oui tu as raison. Cela modifie l'heure de l'horloge de la machine hôte. Relisez simplement la question et réalisez la question, en effet, explicitement mentionnée de NE PAS changer l'horloge de la machine hôte. Je me tiens corrigé :)
Oleg Kazakov
0

Démarrez le conteneur avec une variable d'environnement supplémentaire:

docker run -e "SET_CONTAINER_TIMEZONE=true" \
           -e "CONTAINER_TIMEZONE=US/Arizona" [docker image name]
13dimitar
la source
Je cherche un moyen de régler l'heure de manière dynamique, ce qui signifie qu'il peut être réglé au moment de l'exécution. J'ai mis à jour ma question.
Vingtoft
0

solution docker-compose:

Ajoutez /etc/localtime:/etc/localtime:roà l' volumesattribut.

Regardez ce lien pour un exemple.

Benyamin Jafari
la source