So legen Sie die Systemzeit dynamisch in einem Docker-Container fest

28

Gibt es eine Möglichkeit, die Systemzeit eines Docker-Containers dynamisch (zur Laufzeit) festzulegen, ohne dass dies Auswirkungen auf den Host-Computer hat?

Verwenden

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

gibt den folgenden Fehler aus:

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.

Verwenden

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

gibt den folgenden Fehler aus:

date: cannot set date: Operation not permitted

Anwendungsfall:

Ich muss zeitkritische Software testen (das Verhalten hängt vom Datum ab).

Andere häufige Anwendungsfälle:

  • Ausführen von Legacy-Software mit y2k-Fehlern
  • Testsoftware für die Jahr-2038-Compliance
  • Debuggen von zeitbezogenen Problemen, z. B. abgelaufene SSL-Zertifikate
  • Ausführen von Software, die außerhalb eines bestimmten Zeitraums nicht mehr ausgeführt wird
  • deterministische Build-Prozesse.
Vingtoft
quelle
Welchen Zweck hätte das? Was ist Ihr Anwendungsfall?
Dawud
Bitte siehe bearbeiten.
Vingtoft
1
Eigentlich habe ich gerade eine Lösung mit der libfaketime github.com/wolfcw/libfaketime gefunden und positiv getestet. Ich werde sie in Kürze mit einem answer + working-Beispiel aktualisieren.
Vingtoft

Antworten:

21

Es ist möglich

Die Lösung ist, es im Behälter zu fälschen. Diese Bibliothek fängt alle Systemaufrufprogramme ab, die zum Abrufen der aktuellen Uhrzeit und des aktuellen Datums verwendet werden.

Die Implementierung ist einfach. Fügen Sie Ihrer Docker-Datei nach Bedarf Funktionen hinzu:

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

Denken Sie daran, die Umgebungsvariablen festzulegen, LD_PRELOADbevor Sie die Anwendung ausführen, auf die die gefälschte Zeit angewendet werden soll.

Beispiel:

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]

Sie können die Serverzeit jetzt dynamisch ändern:

Beispiel:

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
quelle
6
Wenn Sie zu dieser Lösung kommen, beachten Sie, dass dies nicht für Golang-Anwendungen oder andere statisch verknüpfte Exes funktioniert.
Sentinel
5
Danke @Sentinel. Witzigerweise habe ich diese Antwort gerade über Google gefunden. Ich möchte sie speziell mit einer Golang-App verwenden, und ich habe festgestellt, dass Sie diesen Kommentar zu einer 1,5 Jahre alten Frage erst vor 2 Stunden hinterlassen haben. Ich fühle mich wie es für mich war. Vielen Dank! :)
dimonomid
Warum ist in deiner Situation keine Arbeit? Verwendet Golang keine Systemaufrufe, um die Zeit abzurufen? @dimonomid Ich schlage vor, Sie probieren es aus, es ist schnell, die Lösung zu implementieren.
Vingtoft
1
@Vingtoft Lass es mich wissen, wenn es tatsächlich funktioniert, aber such herum. Golang verknüpft die Bibliotheken nicht dynamisch.
Sentinel
1
@dimonomid Ja, ich war ziemlich enttäuscht. Eher enttäuscht von Docker. Ich muss zeitbezogene Tests implementieren. Dies macht Docker als "Container" so gut wie unbrauchbar. Ich hätte gedacht, dass das Abfangen von Systemzeitaufrufen für die Zeitzonensynchronisierung Punkt 1 auf der Docker-Agenda gewesen wäre. Scheinbar nicht.
Sentinel
4

Jenny D hat insofern Recht, als der Docker-Container standardmäßig keinen Zugriff auf die Systemuhr zulässt.

Unter Linux können Sie diese Funktion jedoch mit der Option "--cap-add = SYS_TIME" des Befehls "docker run" zulassen, wenn Ihr Container Zugriff auf diese Funktion hat:

# 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

Dann können Sie die Zeit im laufenden Container ändern:

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

Referenzdokumentation: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

Oleg Kazakov
quelle
2
Dies ändert die Zeit auf dem Hostcomputer. Die Zeit auf einem Linux-System ist derzeit nicht namengebunden, es gibt nur einen Wert für den Host und alle Container.
BMitch
Ja, du hast Recht. Dadurch wird die Uhrzeit der Host-Uhr geändert. Lesen Sie die Frage einfach noch einmal durch und realisieren Sie die Frage, die ausdrücklich erwähnt wurde, dass die Uhr des Host-Rechners NICHT geändert werden darf. Ich stehe korrigiert :)
Oleg Kazakov
0

Starten Sie den Container mit einer zusätzlichen Umgebungsvariablen:

docker run -e "SET_CONTAINER_TIMEZONE=true" \
           -e "CONTAINER_TIMEZONE=US/Arizona" [docker image name]
13dimitar
quelle
Ich suche nach einer Möglichkeit, die Zeit dynamisch einzustellen, was bedeutet, dass sie zur Laufzeit eingestellt werden kann. Ich habe meine Frage aktualisiert.
Vingtoft
0

Docker-Compose-Lösung:

In /etc/localtime:/etc/localtime:roan das volumesAttribut.

Schauen Sie sich diesen Link für ein Beispiel an.

Benyamin Jafari
quelle