Возможно ли изменение даты в контейнере докера?

У меня есть контейнер с запущенной программой внутри tomcat. Мне нужно изменить дату только в этом контейнере и проверить поведение моей программы. У меня есть чувствительная ко времени логика, и иногда нужно видеть, что происходит через несколько дней или месяцев. Возможно ли это в докер? Я прочитал, что если я изменю дату в контейнере, дата будет изменена на хост-системе. Но это плохая идея для меня. Мне нужно иметь несколько экземпляров этого приложения на одном сервере и иметь возможность настроить различное время для каждого экземпляра.

Но когда я пытаюсь изменить дату внутри контейнера, я получаю ошибку:

sudo date 04101812
date: cannot set date: Operation not permitted
Fri Apr 10 18:12:00 UTC 2015

Ответ 1

Очень возможно динамически изменять время в контейнере Docker, не влияя на операционную систему хоста.

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

Реализация проста. Добавьте функциональность в ваш 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]

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

Пример:

def set_time(request):
    import os
    import datetime
    print(datetime.datetime.today())
    os.environ["FAKETIME"] = "2020-01-01"  #  string must be "YYYY-MM-DD hh:mm:ss" or "+15d"
    print(datetime.today())

Ответ 2

Это невозможно с докером. Docker использует те же часы, что и внешнее ядро. Что вам нужно, так это полная виртуализация, которая эмулирует полноценный ПК.

sudo потому что она делает вас root виртуальной среды внутри контейнера. Этот пользователь не имеет отношения к реальному root хост-системы (кроме как по имени и UID) и не может делать то, что мог бы сделать настоящий root.

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

Специально для Java используйте joda-time. Там вы можете ввести свой собственный источник времени, используя DateTimeUtils.setCurrentMillis*().

Ответ 3

Это сработало для меня, возможно, вы могли бы попробовать:

dpkg-reconfigure tzdata​​p >

Изменить: выполнить его внутри контейнера, в котором возникают проблемы. Появится интерфейс. Там вы можете отредактировать часовой пояс и местное время, например, и установить его правильно, что исправило мою проблему, которая была такой же, как ваша.

Удачи!

Ответ 4

Для меня мне фактически нужно было установить реальную дату тестирования. Я обнаружил, что следующие опции работают на Mac, но вы должны понимать, что вы будете изменять дату для всех ваших контейнеров, потому что вы меняете дату базовой Alpine VM, которую Docker использует для всех своих контейнеров.

ВАРИАНТ 1: измените дату вашего хост-компьютера и перезапустите докер

Используйте это когда:

  • Вы можете перезапустить докер.
  • Вы можете изменить дату вашего хоста

шаги:

  1. Остановите ваши контейнеры.
  2. Измените дату вашего устройства через настройки даты и времени.
  3. Перезапустите докер.
  4. Начните свои контейнеры.

Запустите эту последовательность еще раз, чтобы вернуться к нужной дате и времени.

ВАРИАНТ 2: Изменить дату Alpine VM

Используйте это когда:

  • Вы не можете перезапустить докер.
  • Вы не можете установить дату своего хоста

шаги:

  1. screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty
    • Экран начинает пустой, нажмите ввод несколько раз.
  2. date -s [hh:mm]
    • Теперь у всех ваших док-контейнеров будет новое время. Вы также можете использовать другие форматы, ищите документацию по "дате занятости", поскольку она не совсем совпадает с другими реализациями даты.
  3. Чтобы выйти, нажмите control-a : и введите d
    • Это отсоединяет сеанс экрана, но оставляет tty запущенным.

Чтобы сбросить время:

  1. screen -r
    • Это возобновляет ваш tty.
  2. ntpd -q
    • При этом используется сервер, определенный в /etc/ntp.conf (это похоже на волшебный мост назад к часам хоста)
  3. Чтобы выйти, нажмите control-a : и наберите quit
    • Это завершает ваш экран и tty сессию.

Ответ 5

Я создал образ Docker, содержащий libfaketime для использования с Alpine, но этот процесс можно выполнить в других дистрибутивах.

Вот пример использования Java с использованием Groovy в качестве примера. Но можно использовать и Tomcat.

FROM groovy:alpine
COPY --from=trajano/alpine-libfaketime  /faketime.so /lib/faketime.so
ENV LD_PRELOAD=/lib/faketime.so \
    DONT_FAKE_MONOTONIC=1

Затем создайте и FAKETIME переменную среды FAKETIME при FAKETIME

docker build -f fakedemo-java.Dockerfile . -t fakedemo
docker run --rm -e FAKETIME=+15d fakedemo groovy -e "print new Date();"

Источник находится в https://github.com/trajano/alpine-libfaketime, а образ докера находится в https://hub.docker.com/r/trajano/alpine-libfaketime

Я также создал его вариант на основе Ubuntu https://github.com/trajano/ubuntu-faketime

Ответ 6

Да, я протестировал его, и он работает!

используйте --privileged при запуске изображения

Пример:

docker run -i -t --rm --privileged my_image /bin/bash