Время и часовой пояс контейнера Docker (не будут отражать изменения)

Откуда контейнеры Docker получают информацию о своем времени? Я создал несколько контейнеров из базового образа ubuntu:trusted, и когда я запускаю его и запрашиваю "дату", я получаю время UTC.

Некоторое время я обходил это, выполняя следующие действия в моем файле Dockerfile:

RUN sudo echo "America/Los_Angeles" > /etc/timezone

Однако по какой-то причине это перестало работать. Поискав в Интернете, я увидел следующее предложение:

docker run -v /etc/timezone:/etc/timezone [image-name]

Однако оба этих метода правильно устанавливают часовой пояс!

$ cat /etc/timezoneAmerica/Los_Angeles$ dateTue Apr 14 23:46:51 UTC 2015

Кто-нибудь знает, что это дает?

Секрет здесь в том, что dpkg-reconfigure tzdata просто создает /etc/localtime как копия, жесткая ссылка или символическая ссылка (предпочтительна символическая ссылка) на файл в /usr/share/zoneinfo. Таким образом, это можно сделать полностью из вашего файла Dockerfile. Считать:

ENV TZ=America/Los_AngelesRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

И в качестве бонуса, TZ также будет правильно установлен в контейнере.

Это также не зависит от дистрибутива, поэтому работает практически с любым Linux.

Примечание: если вы используете изображение на основе alpine, вам необходимо установить tzdata первый. (см. Этот выпуск здесь)

Выглядит так:

RUN apk add --no-cache tzdataENV TZ America/Los_Angeles

Обычно достаточно установить переменную среды в контейнере docker, например:

docker run -e TZ=Europe/Amsterdam debian:jessie date

Конечно, это сработало бы и с docker-compose.

Вы можете добавить свои локальные файлы (/etc/timezone и /etc/localtime) в качестве тома в свой докер-контейнер.

Обновите свой docker-compose.yml со следующими строками.

volumes:    - "/etc/timezone:/etc/timezone:ro"    - "/etc/localtime:/etc/localtime:ro"

Теперь время в контейнере такое же, как и на вашем хосте

Монтаж /etc/localtime на изображении, так что он синхронизирован с host -v является самым популярным из них.

Но видишь выпуск 12084:

это неверно, потому что оно не работает, когда программное обеспечение требует вместо этого файл /etc/timezone быть установленным.
Тот способ, который вы используете, оставляет его в качестве значения по умолчанию etc/UTC.

Я определил, что на самом деле не существует надежного элегантного способа установить часовой пояс внутри контейнера docker.
Итак, мы наконец остановились на этом решении:

Докер-файл приложения:

# Relocate the timezone fileRUN mkdir -p /config/etc && mv /etc/timezone /config/etc/ && ln -s /config/etc/timezone /etc/

Сценарий точки входа в приложение:

# Set timezone as specified in /config/etc/timezonedpkg-reconfigure -f noninteractive tzdata

Объем данных /config dockerfile, локализованный для определенной страны или региона:

# Set the time zoneRUN echo "Europe/London" > /config/etc/timezone

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

Однако он работает должным образом и успешно обеспечивает разделение между базовым образом приложения и каждой локализованной конфигурацией для каждой страны.
В 3 строках кода.

В образе ubuntu 16.04 есть ошибка. Решение было

    ENV TZ 'Europe/Tallinn'    RUN echo $TZ > /etc/timezone && \    apt-get update && apt-get install -y tzdata && \    rm /etc/localtime && \    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \    dpkg-reconfigure -f noninteractive tzdata && \    apt-get clean

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

Однако это сделало свое дело:

ENV TZ=America/TorontoRUN apk updateRUN apk upgradeRUN apk add ca-certificates && update-ca-certificatesRUN apk add --update tzdataRUN rm -rf /var/cache/apk/*

[Источник]

В базовом изображении alpine (пример использования узла: 10.16.0-alpine):

Файл Dockerfile

FROM node:10.16.0-alpineENV TZ=America/Los_AngelesRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezoneWORKDIR /appCOPY package.json package-lock.json ./RUN npm i --productionCOPY . .CMD node index.js

Использование контейнера Fedora (вероятно, также будет работать с ubuntu):

Самым простым решением, которое я нашел, было использовать следующее в docker-compose.yml

environment:   TZ: "${TZ:-America/Los_Angeles}"

Затем в вашем файле .env (который автоматически считывается docker-compose)

TZ=America/Los_Angeles

Это позволяет вам поместить docker-compose.yml под контроль версий и использовать настроенный файл .env, который git может игнорировать.

Вы получаете значение по умолчанию для контейнера и получаете настройку, лучшее из обоих миров.

Для Fedora никаких других изменений не требовалось, она просто работает!

если вы используете изображение docker на основе ubuntu :

# Change the docker default timezone from UTC to SGTecho "Asia/Singapore" > /etc/timezonedpkg-reconfigure tzdatadate

Спасибо VonC за информацию и ссылку на проблему. Это кажется таким запутанным беспорядком, поэтому я провел некоторое тестирование своей собственной идеи о том, как решить эту проблему, и, похоже, она отлично работает.

>docker run -it ubuntu:trusty /bin/bash#dpkg-reconfigure tzdata

(следуйте инструкциям, чтобы выбрать мой часовой пояс)

>docker commit [container-id] chocko/ubuntu:local

Затем я обновил свои файлы Dockerfiles, чтобы отразить это:

FROM chocko/ubuntu:local

Должно быть, в этом что-то не так, потому что кажется, что это слишком легко упустить из виду... Или это приемлемо?

Если вы используете Alpine, вам необходимо сначала установить tzdata, см. Здесь How can I set the timezone please? · Issue #136 · gliderlabs/docker-alpine · GitHub

К вашему сведению … я хочу установить часовой пояс контейнера во время выполнения docker, а не во время сборки docker / dockerfile. Использование -v /etc/localtime:/etc/localtime:ro (CentOS) вроде как работает. Внутренняя дата командной строки контейнера возвращает дату в ожидаемом формате часового пояса. НО дженкинс, работающий в контейнере, считает, что часовой пояс - UTC. Почему? /etc/localtime - это символическая ссылка на …/usr/share/zoneinfo/UTC во встроенном контейнере. Содержимое файла UTC в контейнере теперь является новым часовым поясом. Но дженкинс (и, возможно, другое программное обеспечение на базе java) использует имя символической ссылки, которое по-прежнему является “UTC”. В поисках решения. . .

Нужны 2 вещи: 1. при создании контейнера используйте сценарий инициализации для установки символической ссылки /etc/localtime и /etc/timezone и 2. поскольку часовой пояс дженкинса берется из двух параметров java, эти параметры необходимо передать сценарию инициализации, который запускает процесс дженкинса. например " -Dorg.apache.commons.jelly.tags.fmt.Часовой пояс=Америка/Нью_Йорк -Duser.часовой пояс=Америка/Нью_Йорк ". Прошу прощения, это специфично для Дженкинса, но, надеюсь, полезно для некоторых других пользователей Дженкинса.