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

136

Где контейнеры Docker получают информацию о времени? Я создал несколько контейнеров из базового Ubuntu: надежного образа, и когда я запускаю его и запрашиваю «дату», я получаю время UTC.

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

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

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

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

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

$ cat /etc/timezone
America/Los_Angeles
$ date
Tue Apr 14 23:46:51 UTC 2015

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

Chockomonkey
источник
3
Если вы используете Alpine, вам нужно tzdataсначала установить , см. Здесь github.com/gliderlabs/docker-alpine/issues/136
Belter
1
К вашему сведению , , Я хочу установить часовой пояс контейнера во время выполнения Docker, а не во время сборки / Dockerfile. Использование -v /etc/localtime:/etc/localtime:ro(CentOS) рода работ. Внутри контейнера в командной строке date возвращает дату в формате ожидаемого часового пояса. НО Дженкинс, бегущий в контейнере, думает, что часовой пояс - UTC. Почему? / etc / localtime является символической ссылкой на ../usr/share/zoneinfo/UTC во встроенном контейнере. Содержимое файла UTC в контейнере теперь является новым часовым поясом. Но jenkins (и, возможно, другое программное обеспечение на основе Java) используют имя символической ссылки, которая все еще "UTC". В поисках решения. , ,
gaoithe
1
Нужно 2 вещи: 1. при создании контейнера используйте сценарий инициализации для установки символьной ссылки / etc / localtime и / etc / timezone и 2. для часового пояса jenkins берется два параметра java, эти параметры необходимо передать в сценарий инициализации, который запускает процесс Дженкинса. например, "-Dorg.apache.commons.jelly.tags.fmt.timeZone = America / New_York -Duser.timezone = America / New_York". Извините, это специфично для jenkins, но, надеюсь, полезно для некоторых других пользователей jenkins
Гаоит

Ответы:

210

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

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

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

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

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

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

RUN apk add --no-cache tzdata
ENV TZ America/Los_Angeles
Майкл Хэмптон
источник
20
Список имен TZ: en.wikipedia.org/wiki/List_of_tz_database_time_zones
BillyTom
5
В Ubuntu: 16.04 (и, возможно, в другой версии) вам нужно установить tzdataпакет для этой работы.
Opsse
6
Я единственный, кто думает, что не очень разумно жестко кодировать часовой пояс в Dockerfile?
Вольфганг
1
@Wolfgang Это пример. Вы можете предоставить это любым другим способом, которым вы обычно предоставляете переменные окружения, такие как командная строка, docker-compose.yml и т. Д.
Майкл Хэмптон
Я заметил, что, по крайней мере для изображений на основе Alpine, достаточно просто установить TZпеременную. Мне не нужно было устанавливать символические ссылки или что-то еще.
code_dredd
59

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

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

Конечно, это будет работать и с docker-compose.

Виктор Клос
источник
2
Это кажется самым элегантным способом. Позаботьтесь о том, чтобы у некоторого базового образа, например ubuntu:16.04, не было tzdataпакета, который следует добавить в Dockerfile.
Жюльен Фастре
1
+1 - я согласен с Жюльеном; это, кажется, самый элегантный подход для установки часовых поясов во время выполнения. Это хорошо работает с CentOS. Для Alpine-образа требуется установка пакета 'tzdata', который предпочтительнее, чем конфигурация harcoding во время сборки, за исключением случаев, когда дополнительная нагрузка на образ 3
МБ
Это кажется хорошим, но, кажется, не работает для меня (с CentOS 7.5.1804 и tzdata-2018e-3.el7.noarch)? грустное лицо
gaoithe
22

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

Но смотрите выпуск 12084 :

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

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

Приложение dockerfile:

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

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

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

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

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

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

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

VonC
источник
1
Для меня это было: RUN echo "Europe/London" > /etc/timezone
jpmottin
@jpmottin Так немного как на serverfault.com/a/856593/783 тогда?
VonC
18

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

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

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

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

thhan
источник
Если на хосте дистрибутива CentOS введите команду echo "Europe/Paris" > /etc/timezoneперед перезапуском контейнера.
CrazyMax
Это работает на хосте MacOS?
Redsandro
Не работает в MAC
Марчелло де Сэйлс
Раньше это работало на MacOS, но я просто попробовал снова через долгое время, и я получил следующее. Не уверен, что High Sierra или изменение docker вызвало следующее: "docker: Ответ об ошибке от демона: Монтирование отказано: путь / etc / localtime не является общим для OS X и не известен Docker. Вы можете настроить общие пути из Docker - > Настройки ... -> Общий доступ к файлам. Для получения дополнительной информации см. Docs.docker.com/docker-for-mac/osxfs/#namespaces . "
gae123
1
Это приведет к повреждению вашей базы данных zoneinfo, так как / etc / localtime является символической ссылкой (таким образом / usr / share / zoneinfo / Some / Thing, вероятно, будет смонтирован как / usr / share / zoneinfo / UTC внутри контейнера). Не говоря уже о том, что вы бы смешали файл базы данных с хоста с файлом в контейнере.
ionelmc
12

В образе 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
БУКВ
источник
1
Серьезно ... это единственное решение, которое сработало!
Геррат
1
Также пришлось это сделать - кажется, tzdata больше не находится в некоторых дистрибутивах по умолчанию.
Питер
4

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

# Change the docker default timezone from UTC to SGT
echo "Asia/Singapore" > /etc/timezone
dpkg-reconfigure tzdata
date
Xianlin
источник
3

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

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

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

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

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

FROM chocko/ubuntu:local

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

Chockomonkey
источник
Это также то, что я пытался, но часовой пояс все еще сбрасывает себя после того, как я exitконтейнер. Это на Debian.
Майк Чемберлен
@MikeChamberlain Вы случайно не попробовали принятый ответ Майкла Хэмптона выше? Я не реализовал это сам, но я считаю, что это путь, чтобы рассмотреть положительные отзывы, которые он получил.
Chockomonkey
2

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

Тем не менее, это сделало свое дело:

ENV TZ=America/Toronto
RUN apk update
RUN apk upgrade
RUN apk add ca-certificates && update-ca-certificates
RUN apk add --update tzdata
RUN rm -rf /var/cache/apk/*

[ Источник ]

Альфа
источник
1

Более общий способ установить часовой пояс в docker runаргументах:

-e TZ=`ls -la /etc/localtime | cut -d/ -f8-9`

Или для повторного использования:

function GET_TZ () {
    ls -la /etc/localtime | cut -d/ -f8-9
}

...
-e TZ=`GET_TZ`
Mugen
источник
не помогает, если ваш базовый образ - альпийский (5 МБ), на котором не установлена ​​"tzdata"
max4ever