Как динамически установить системное время в контейнере Docker

28

Есть ли способ установить системное время Docker-контейнеров динамически (во время выполнения), не влияя на хост-компьютер?

С помощью

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

выдает следующую ошибку:

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.

С помощью

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

выдает следующую ошибку:

date: cannot set date: Operation not permitted

Случай использования:

Мне нужно протестировать чувствительное ко времени программное обеспечение (поведение зависит от даты).

Другие распространенные случаи использования:

  • запуск устаревшего программного обеспечения с ошибками y2k
  • тестирование программного обеспечения на соответствие требованиям 2038 года
  • отладка связанных со временем проблем, таких как истекшие сертификаты SSL
  • запуск программного обеспечения, которое перестает работать вне определенного периода времени
  • детерминированные процессы сборки.
Vingtoft
источник
Какова будет цель сделать это? какой у вас вариант использования?
Дауд
Пожалуйста, смотрите редактировать.
Vingtoft
1
На самом деле, я только что нашел и положительно протестировал решение, используя libfaketime github.com/wolfcw/libfaketime, который я скоро обновлю с ответом + рабочим примером.
Vingtoft

Ответы:

21

Возможно

Решение состоит в том, чтобы подделать его в контейнере. Эта библиотека перехватывает все программы системных вызовов, используемые для получения текущего времени и даты.

Реализация проста. Добавьте функциональность в ваш Dockerfile соответствующим образом:

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

Не забудьте установить переменные среды, LD_PRELOADпрежде чем запускать приложение, к которому вы хотите применить фиктивное время.

Пример:

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]

Теперь вы можете динамически изменять время сервера:

Пример:

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
источник
6
Для других, приходящих к этому решению, имейте в виду, что это не будет работать для приложений golang или других статически связанных exe.
Страж
5
Спасибо @ Сентинел. Как ни странно, я только что нашел этот ответ через Google, я специально хочу использовать его с приложением golang, и я заметил, что вы оставили этот комментарий на вопрос 1,5 лет всего 2 часа назад. Такое ощущение, что это было для меня. Благодарность! :)
димономид
Почему не работает в вашей ситуации? Разве Голанг не использует системные вызовы для получения времени? @dimonomid Я предлагаю вам попробовать, это быстро реализовать решение.
Vingtoft
1
@ Vingtoft Дайте мне знать, если это действительно работает, но поиск вокруг. Голанг не динамически связывается в библиотеках.
Страж
1
@dimonomid Да, я был очень разочарован. Больше разочарован Docker на самом деле. Мне нужно реализовать временные тесты. Это делает Docker практически бесполезным в качестве «контейнера». Я бы подумал, что перехват системных вызовов времени для синхронизации часовых поясов был бы пунктом 1 повестки дня Докера. Очевидно нет.
Страж
4

Jenny D прав в том, что по умолчанию контейнер Docker не разрешает доступ к системным часам.

Однако в Linux, если у вас все в порядке с вашим контейнером, имеющим доступ к этой возможности, вы можете разрешить эту возможность, используя опцию «--cap-add = SYS_TIME» команды «docker run» при создании вашего контейнера:

# 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

Затем вы можете изменить время внутри запущенного контейнера:

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

Справочная документация: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

Олег Казаков
источник
2
Это меняет время на главном компьютере. Время в системе Linux в настоящее время не является пространством имен, есть только одно значение для хоста и всех контейнеров.
BMitch
Да, ты прав. Это изменяет время часов хост-машины. Просто перечитал вопрос и понял вопрос, действительно, прямо упомянул про НЕ меняющий часы хост-машины. Стою исправлюсь :)
Олег Казаков
0

Запустите контейнер с дополнительной переменной среды:

docker run -e "SET_CONTAINER_TIMEZONE=true" \
           -e "CONTAINER_TIMEZONE=US/Arizona" [docker image name]
13dimitar
источник
Я ищу способ установить время динамически, то есть его можно установить во время выполнения. Я обновил свой вопрос.
Vingtoft
0

docker-compose решение:

Добавьте /etc/localtime:/etc/localtime:roк volumesатрибуту.

Посмотрите на эту ссылку для примера.

Беньямин Джафари
источник