Docker Container время и часовой пояс (не будет отражать изменения)
Где контейнеры 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
Кто-нибудь знает, что дает?
12 ответов
Секрет в том, что 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
Обычно достаточно установить переменную окружения в контейнере Docker, например, так:
docker run -e TZ=Europe/Amsterdam debian:jessie date
Конечно, это будет работать и с docker-compose
,
Вы можете добавить свои локальные файлы (/etc/timezone и /etc/localtime) в виде тома в ваш docker-контейнер.
Обновите свой docker-compose.yml
со следующими строками.
volumes:
- "/etc/timezone:/etc/timezone:ro"
- "/etc/localtime:/etc/localtime:ro"
Теперь время контейнера такое же, как на вашем хосте.
Монтаж /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
Объем данных
/config
Dockerfile, локализованный для конкретной страны или региона:
# Set the time zone
RUN 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
Если вы используете образ докера на основе ubuntu
:
# Change the docker default timezone from UTC to SGT
echo "Asia/Singapore" > /etc/timezone
dpkg-reconfigure tzdata
date
Здесь я добавляю свои два цента, потому что я пробовал несколько из них, но ни один не работал на альпийских изображениях.
Тем не менее, это сделало свое дело:
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/*
[ Источник]
Использование контейнера Fedora (вероятно, будет работать и с Ubuntu):
Самым простым решением, которое я нашел, было использование следующего в docker-compose.yml:
environment:
TZ: "${TZ:-America/Los_Angeles}"
Затем в вашем файле .env (который автоматически читает docker-compose)
TZ=America/Los_Angeles
Это позволяет вам поставить docker-compose.yml под контроль версий и использовать настроенный файл .env, который может игнорироваться git.
Вы получаете значение по умолчанию для контейнера и получаете возможность настройки, лучшее из обоих миров.
Для Fedora никаких других изменений не потребовалось, она просто работает!
В базовом образе alpine (пример использования узла:10.16.0-alpine):
Dockerfile
FROM node:10.16.0-alpine
ENV TZ=America/Los_Angeles
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm i --production
COPY . .
CMD node index.js
Спасибо VonC за информацию и ссылку на проблему. Это кажется таким запутанным беспорядком, поэтому я проверил свою идею о том, как решить эту проблему, и это, кажется, прекрасно работает.
>docker run -it ubuntu:trusty /bin/bash
#dpkg-reconfigure tzdata
(следуйте инструкциям, чтобы выбрать мой часовой пояс)
>docker commit [container-id] chocko/ubuntu:local
Затем я обновил свои файлы Docker, чтобы отразить это:
FROM chocko/ubuntu:local
Должно быть, с этим что-то не так, потому что кажется, что это слишком легко игнорировать... Или это приемлемо?
Более общий способ установить часовой пояс в 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`
Самый простой способ — добавить-e
вариант илиENV
директива для установкиTZ
переменная среды, поскольку debian, ubuntu и т. д. уже включеныtzdata
.
Кто-то рекомендует смонтировать часовой пояс с хоста:
$ docker run -it --rm \
-v /etc/localtime:/etc/localtime \
-v /etc/timezone:/etc/timezone \
debian:bullseye date
Mon Jul 3 19:41:30 CST 2023
Это может сработать, но это опасно. Потому что/etc/localtime
на самом деле это ссылка на символ (в некоторых новых дистрибутивах), и Docker по умолчанию следует по ссылке на символ. В результате данные часового пояса (вместо самой ссылки на символ) переопределяются автоматически.
$ docker run -it --rm debian:bullseye \
sh -c 'ls -l /etc/localtime && tail -n1 /etc/localtime'
lrwxrwxrwx 1 root root 27 Mar 20 00:00 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
UTC0
$ docker run -it --rm -v /etc/localtime:/etc/localtime debian:bullseye \
sh -c 'ls -l /etc/localtime && tail -n1 /etc/localtime'
lrwxrwxrwx 1 root root 27 Mar 20 08:00 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
CST-8
Вот почему это не работает:
$ docker run -it --rm \
-v /usr/share/zoneinfo:/usr/share/zoneinfo \
-v /etc/localtime:/etc/localtime \
-v /etc/timezone:/etc/timezone \
debian:bullseye date
Mon Jul 3 11:41:59 UTC 2023