Jak dynamicznie ustawić czas systemowy w kontenerze Docker

28

Czy jest jakiś sposób na dynamiczne ustawienie czasu systemowego kontenerów Docker (w czasie wykonywania) bez wpływu na maszynę hosta?

Za pomocą

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

daje następujący błąd:

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.

Za pomocą

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

daje następujący błąd:

date: cannot set date: Operation not permitted

Przypadek użycia:

Muszę przetestować oprogramowanie wrażliwe na czas (zachowanie zależy od daty).

Inne typowe przypadki użycia:

  • działające starsze oprogramowanie z błędami y2k
  • testowanie oprogramowania pod kątem zgodności z rokiem 2038
  • debugowanie problemów związanych z czasem, takich jak wygasłe certyfikaty SSL
  • uruchomione oprogramowanie, które przestaje działać poza określonym czasem
  • deterministyczne procesy budowania.
Vingtoft
źródło
Jaki byłby tego cel? jaki jest twój przypadek użycia?
dawud
Proszę zobaczyć edycję.
Vingtoft,
1
Właściwie właśnie znalazłem i pozytywnie przetestowałem rozwiązanie przy użyciu libfaketime github.com/wolfcw/libfaketime. Zaktualizuję go krótko + działającym przykładem.
Vingtoft,

Odpowiedzi:

21

To jest możliwe

Rozwiązaniem jest sfałszowanie go w pojemniku. Ta biblioteka przechwytuje wszystkie programy wywołań systemowych używane do pobierania bieżącej godziny i daty.

Wdrożenie jest łatwe. Dodaj funkcjonalność do pliku Docker odpowiednio:

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

Pamiętaj, aby ustawić zmienne środowiskowe LD_PRELOADprzed uruchomieniem aplikacji, której dotyczy fałszywy czas.

Przykład:

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]

Możesz teraz dynamicznie zmieniać czas serwerów:

Przykład:

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
źródło
6
W przypadku innych osób korzystających z tego rozwiązania należy pamiętać, że nie będzie to działać w aplikacjach golang ani innych statycznie powiązanych ex.
Sentinel,
5
Dzięki @Sentinel. Zabawne jest to, że właśnie znalazłem tę odpowiedź za pośrednictwem Google'a. Chciałbym jej użyć z aplikacją Golang i zauważyłem, że komentarz zostawiłeś na 1,5-letnie pytanie zaledwie 2 godziny temu. Czuję, że to było dla mnie. Dzięki! :)
dimonomid
Dlaczego nie działa w twojej sytuacji? Czy Golang nie używa wywołań systemowych do pobierania czasu? @dimonomid Proponuję spróbować, szybko można wdrożyć rozwiązanie.
Vingtoft,
1
@ Vingtoft Daj mi znać, czy to rzeczywiście działa, ale szukaj. Golang nie łączy się dynamicznie w bibliotekach.
Sentinel,
1
@dimonomid Tak, byłem bardzo rozczarowany. Bardziej rozczarowany Dockerem. Muszę wdrożyć testy związane z czasem. To sprawia, że ​​Docker jest praktycznie bezużyteczny jako „kontener”. Myślałem, że przechwytywanie systemowych wezwań czasowych do synchronizacji strefy czasowej byłoby pozycją 1 w programie Docker. Najwyraźniej nie.
Sentinel,
4

Jenny D ma rację, ponieważ domyślnie kontener Docker nie pozwala na dostęp do zegara systemowego.

Jednak w systemie Linux, jeśli twój kontener ma dostęp do tej możliwości, możesz na to pozwolić, używając opcji „--cap-add = SYS_TIME” komendy „runer run” podczas tworzenia kontenera:

# 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

Następnie możesz zmienić czas z działającego kontenera:

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

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

Oleg Kazakow
źródło
2
To zmienia czas na hoście. Czas w systemie Linux nie ma obecnie przestrzeni nazw, istnieje tylko jedna wartość dla hosta i wszystkich kontenerów.
BMitch
Tak, masz rację. Zmienia to czas zegara komputera hosta. Wystarczy ponownie przeczytać pytanie i zdać sobie sprawę, że pytanie zostało wyraźnie wymienione na temat NIE zmieniania zegara komputera-hosta. Stoję skorygowany :)
Oleg Kazakov
0

Uruchom kontener z dodatkową zmienną środowiskową:

docker run -e "SET_CONTAINER_TIMEZONE=true" \
           -e "CONTAINER_TIMEZONE=US/Arizona" [docker image name]
13dimitar
źródło
Szukam sposobu, aby ustawić czas dynamicznie, co oznacza, że ​​można go ustawić w czasie wykonywania. Zaktualizowałem moje pytanie.
Vingtoft,
0

rozwiązanie dokowania-komponowania:

Dodaj /etc/localtime:/etc/localtime:rodo volumesatrybutu.

Spójrz na ten link jako przykład.

Benyamin Jafari
źródło