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


135

Звідки контейнери 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

Хтось знає, що дає?


3
Якщо ви користуєтесь Alpine, вам потрібно встановити tzdataспочатку, дивіться тут github.com/gliderlabs/docker-alpine/isissue/136
Belter

1
FYI. . . Я хочу встановити часовий пояс контейнера на час роботи докера, а не на час складання докер / докерфайлу. Використання -v /etc/localtime:/etc/localtime:ro(CentOS) роду робіт. Дата командного рядка контейнера повертає дату в очікуваному форматі часового поясу. АЛЕ Джинкіни, що працюють у контейнері, вважають, що часовий пояс є UTC. Чому? / etc / localtime - це посилання на ../usr/share/zoneinfo/UTC у вбудованому контейнері. Вміст файлу UTC в контейнері тепер є новим часовим поясом. Але jenkins (і, можливо, інше програмне забезпечення на базі Java) використовують назву симпосилання, яке досі є "UTC". Пошук рішення. . .
gaoithe

1
Потрібно 2 речі, 1. коли контейнер створений, використовуйте сценарій init для встановлення / etc / localtime symlink та / etc / timezone та 2. для часових поясів jenkins взято два варіанти Java, ці параметри потрібно передати скрипту init, який запускає процес дженкінів. наприклад, "-Dorg.apache.commons.jelly.tags.fmt.timeZone = America / New_York -Duser.timezone = America / New_York". Вибачте, це специфічні для дженкінів, але сподіваємось корисні для деяких інших користувачів дженкінів.
gaoithe

Відповіді:


208

Секрет тут полягає в тому, що 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


5
Для Ubuntu: 16.04 (а може бути й інша версія) для роботи потрібно встановити tzdataпакет.
Опссе

5
Чи я єдиний, хто вважає, що не дуже розумно жорстко кодувати часовий пояс у Dockerfile?
Вольфганг

1
@Wolfgang Це приклад. Ви можете надати його будь-яким іншим способом, як правило, надавали б змінні середовища, наприклад командний рядок, docker-compose.yml тощо.
Майкл Хемптон

Я помітив, що принаймні для зображень на альпійській мові досить просто встановити TZзмінну. Мені не потрібно було налаштовувати посилання або щось інше.
code_dredd

58

Зазвичай достатньо встановити змінну середовища в контейнері докера, наприклад:

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

Звичайно, це працювало б і з docker-compose.


2
Це здається найелегантнішим способом. Слідкуйте за тим, щоб якесь базове зображення, як-от ubuntu:16.04, не було tzdataпакету, який слід додати в Dockerfile.
Жульєн Фастре

1
+1 - я згоден з Жульєном; Це, мабуть, є найелегантнішим підходом для встановлення часових поясів під час виконання. Це добре працює з CentOS. Альпійське зображення вимагає встановлення пакета 'tzdata', який надається перевагу над конфігурацією хакодування в час збирання, якщо додаткове навантаження зображення на 3 МБ не можна допустити :)
Frelling

Це здається гарним, але, здається, не працює для мене (із CentOS 7.5.1804 та tzdata-2018e-3.el7.noarch)? сумне обличчя
gaoithe

22

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

Але див. Випуск 12084 :

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

Я визначив, що насправді не існує надійного елегантного способу встановити часовий пояс всередині докерного контейнера.
Тож нарешті вдалося вирішити це рішення:

Док-файл програми:

# 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

/configДокерфайл обсягу даних, локалізований у конкретній країні чи регіоні:

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

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

Однак він працює належним чином і успішно досягає поділу між базовим зображенням програми та кожною локалізованою конфігурацією для кожної країни.
У 3 рядках коду.


1
Для мене це було: RUN echo "Europe/London" > /etc/timezone
jpmottin

@jpmottin Тож трохи, як у сервері default.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"

Зараз час контейнера такий же, як у вашого хоста


Якщо ваш хост розповсюдження на CentOS, введіть команду echo "Europe/Paris" > /etc/timezoneперед перезавантаженням контейнера.
CrazyMax

Це працює на хості MacOS?
Редсандро

Не ПРАЦЮЄ в MAC
Marcello de Sales

Це працювало на MacOS, але я просто спробував його знову через довгий час, і я отримав наступне. Не впевнений, чи спричинили це Висока Сьєрра або зміна докера: "docker: Відповідь про помилку демона: Mounts відхилено: Шлях / etc / localtime не передається OS X і не відомий Docker. Ви можете налаштувати спільні шляхи з Docker - > Налаштування ... -> Обмін файлами. Докладнішу інформацію див. У docs.docker.com/docker-for-mac/osxfs/#namespaces . "
gae123

1
Це пошкодить вашу зону info db, оскільки / etc / localtime є символьною посиланням (таким чином, / usr / share / zoneinfo / Some / Thing, швидше за все, встановиться як / usr / share / zoneinfo / UTC всередині контейнера). Не кажучи вже про те, що ви змішали б файл db від хоста з тим, який знаходиться в контейнері.
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

3

Дякуємо VonC за інформацію та посилання на випуск. Це здається таким заплутаним безладом, тому я зробив кілька тестів на власну думку про те, як це вирішити, і, здається, це чудово працює.

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

(Дотримуйтесь підказок, щоб вибрати мій часовий пояс)

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

Потім я оновив свої Dockerfiles, щоб відобразити це:

FROM chocko/ubuntu:local

З цим повинно бути щось не так, тому що це здається занадто простим, щоб його не помітити ... Або це прийнятно?


Це теж те, що я спробував, але часовий пояс все одно скидається після того, як я 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`

не допоможе, якщо ваш базовий образ альпійський (5 Мб), на якому не встановлено "tzdata"
max4ever
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.