Поиск по сайту:

Как обрабатывать часовые пояса в контейнерах Docker


Часовые пояса — распространенный источник путаницы при контейнеризации приложения. Будут ли ваши задачи cron выполняться в нужное время? Контейнеры Docker не наследуют часовой пояс хоста, поэтому вы можете столкнуться с неожиданными проблемами планирования, которые нанесут ущерб вашему приложению.

Вот команда date, изначально работающая на хосте Ubuntu 20.04 в часовом поясе британского летнего времени:

А вот та же команда в контейнере на основе немодифицированного образа ubuntu:20.04:

Контейнер использует часовой пояс UTC, создавая разницу в один час между двумя временами.

Как работают часовые пояса Linux?

Большинство дистрибутивов Linux используют пакет tzdata для предоставления информации о часовом поясе. Когда tzdata установлен, вы можете проверить текущий часовой пояс, прочитав файл /etc/timezone:

У вас также будет файл /etc/localtime. Это символическая ссылка на правильную базу данных часовых поясов для выбранного местоположения:

Если вы измените часовой пояс с помощью dpkg-reconfigure tzdata, символическая ссылка /etc/localtime обновится, чтобы указать на новую базу данных. Вывод таких команд, как date, будет скорректирован, чтобы включить смещение активного часового пояса.

Проблема с контейнерами

Проблема с контейнерами в первую очередь связана с установкой часового пояса. Если вы вспомните, когда вы настраивали свой хост, вам нужно было установить часовой пояс как часть установки операционной системы. Когда вы запускаете новый контейнер, он запускается сразу, без этапа «установки». Нет возможности выбрать подходящий часовой пояс.

Теоретически среды выполнения контейнеров могут предлагать автоматическое наследование часового пояса хоста. Этого не происходит, поскольку это может привести к неожиданным результатам при развертывании в удаленных средах. Было бы легко упустить из виду, что ваше расписание cron работает на вашем локальном компьютере, но неожиданно выполняется в управляемом кластере Kubernetes с использованием времени UTC.

Вместо этого образы контейнеров поставляются со встроенным часовым поясом. Для большинства популярных изображений это будет UTC. Многие базовые образы, особенно минимальные, даже не включают пакет tzdata. У вас не будет файлов /etc/timezone или /etc/localtime.

Добавление часовых поясов в ваши контейнеры

Первая часть установки правильного часового пояса заключается в том, чтобы убедиться, что tzdata установлен. Если ваш образ не включает его, вам нужно вручную добавить пакет как часть вашего Dockerfile.

FROM ubuntu:latest
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y tzdata

При установке tzdata вы обычно получаете интерактивную подсказку, позволяющую выбрать правильный часовой пояс из меню. Это бесполезно, когда вы программно создаете контейнеры Docker. Установка переменной среды DEBIAN_FRONTEND подавляет приглашение и устанавливает часовой пояс по умолчанию на UTC.

Как только вы добавили tzdata в свое изображение, вы готовы настроить правильный часовой пояс для своего приложения. Самый простой подход — установить для переменной среды TZ часовой пояс, который вы хотите использовать:

FROM ubuntu:latest
ENV TZ=Europe/London
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y tzdata

При желании вы можете установить переменную TZ при запуске контейнеров. Передайте его как переменную среды в docker run. Это позволяет переопределить часовой пояс изображения по умолчанию, если оно включает пакет tzdata.

docker run -e TZ=Europe/London -it ubuntu:latest

Альтернативой переменным среды является файл /etc/timezone. Вы можете указать требуемый часовой пояс как часть вашего Dockerfile. Если вы используете этот метод, вы должны перенастроить tzdata с помощью вашего менеджера пакетов. Не забудьте использовать неинтерактивный режим, иначе вы снова получите графическое приглашение часового пояса.

FROM ubuntu:latest
RUN echo "Europe/London" > /etc/timezone
RUN dpkg-reconfigure -f noninteractive tzdata

Другие методы

Если вы хотите гарантировать синхронизацию часового пояса с хостом, вы можете смонтировать локальные файлы tzdata в свои контейнеры. Вам все равно понадобится tzdata внутри контейнера, чтобы это работало правильно.

docker run -v /etc/timezone:/etc/timezone -v /etc/localtime:/etc/localtime -it ubuntu:latest

Хотя Docker не предоставляет встроенной поддержки часовых поясов, это верно не для всех контейнерных движков. У Podman есть специальный флаг --tz, который позволяет вам установить часовой пояс при создании нового контейнера:

podman run --tz=Europe/London -it ubuntu:latest

Незаметно Podman смонтирует для вас соответствующий файл /etc/localtime. Указанный часовой пояс будет сохраняться в течение всего срока службы контейнера.

Podman также позволяет установить часовой пояс по умолчанию для контейнеров, созданных без флага --tz. Создайте или отредактируйте .config/containers/containers.conf в своем домашнем каталоге. Добавьте параметр tz в новую строку файла:

# Used when no --tz flag is given
tz = "Europe/London"

Собственная интеграция часовых поясов Podman упрощает работу, чем с Docker. Поскольку интерфейс командной строки Podman совместим с Docker, стоит подумать о переключении, если вы часто работаете с контейнерами в разных часовых поясах.

Краткое содержание

Часовые пояса часто упускают из виду при настройке контейнеров Docker. Большинство базовых изображений по умолчанию используют время UTC, что может привести к путанице, если часовой пояс хоста отличается.

Установив пакет tzdata, ваш контейнер становится совместимым со всеми часовыми поясами через переменную среды TZ, /etc/timezone и / и т.д./местное время. Кроме того, вы можете синхронизировать часовой пояс вашего хоста, установив соответствующие файлы в свои контейнеры.

Наконец, помните, что эти соображения также применимы к размещенным службам Docker и кластерам Kubernetes. Ваши контейнеры будут использовать время UTC, если не указано иное. Пока вы можете устанавливать переменные среды, вы сможете использовать TZ для настройки часового пояса для своих рабочих нагрузок.