Один из самых частых вопросов у тех, кто переносит сервисы в контейнеры на виртуальной машине: приложение внутри контейнера пишет время «не то», отчёты сдвинуты, задания по расписанию срабатывают не тогда.
Почему. Контейнер не наследует часовой пояс хоста. В большинстве базовых образов он UTC, и приложение честно показывает UTC. Разница с локальным временем сервера в несколько часов и есть весь «сбой».
Три способа, от быстрого к правильному.
- Переменная окружения
TZ. Вdocker run -e TZ=Europe/Berlinили в compose-файле в секцииenvironment. Работает, если в образе есть база часовых поясов (пакетtzdata); в минимальных образах её может не быть. - Пробросить файл пояса хоста. Том
-v /etc/localtime:/etc/localtime:ro. Просто, но контейнер становится зависим от настройки хоста и переезд на другой сервер меняет поведение. - Задать в Dockerfile. Установить
tzdata, сделать ссылку/etc/localtimeна нужный пояс и записать имя пояса в/etc/timezone. Самый предсказуемый вариант для образов, которые вы собираете сами.
Что не менять. Системное время самой виртуальной машины должно оставаться синхронизированным и, как правило, в UTC; часовой пояс это только отображение. Если время внутри контейнера отличается не на целое число часов, а «плывёт», проблема не в поясе, а в синхронизации времени на хосте.
Проверка. docker exec <контейнер> date против date на хосте: разница должна быть ровно смещением пояса или нулём.
Статус. Общеизвестная практика, подтверждённая документацией; в исходных обсуждениях авторы выбирали разные из трёх способов.
Переменные окружения и тома описаны в документации Docker.