Docker Container Zeit & Zeitzone (Änderungen werden nicht berücksichtigt)

135

Woher beziehen Docker-Container ihre Zeitinformationen? Ich habe einige Container aus dem grundlegenden ubuntu: trusty-Image erstellt. Wenn ich es ausführe und das Datum abfrage, erhalte ich die UTC-Zeit.

Eine Weile lang habe ich das in meinem Dockerfile so umgangen:

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

Aus irgendeinem Grund funktionierte das jedoch nicht mehr. Bei der Online-Suche habe ich die folgenden Vorschläge gesehen:

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

Beide Methoden stellen die Zeitzone korrekt ein!

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

Weiß jemand was das gibt?

Chockomonkey
quelle
3
Wenn Sie verwenden Alpine, müssen Sie tzdatazuerst installieren , siehe hier github.com/gliderlabs/docker-alpine/issues/136
Belter
1
Zu Ihrer Information. . . Ich möchte die Zeitzone des Containers zur Docker-Laufzeit festlegen, nicht zur Docker-Build- / Docker-Datei-Zeit. -v /etc/localtime:/etc/localtime:roArbeiten mit (CentOS). Das Befehlszeilendatum im Container gibt das Datum im erwarteten Zeitzonenformat zurück. ABER Jenkins, die im Container laufen, denken, dass die Zeitzone UTC ist. Warum? / etc / localtime ist ein Symlink zu ../usr/share/zoneinfo/UTC in einem erstellten Container. Der Inhalt der UTC-Datei im Container ist jetzt die neue Zeitzone. Aber Jenkins (und vielleicht auch andere Java-basierte Software) verwenden den Namen des Symlinks, der immer noch "UTC" ist. Auf der Suche nach einer Lösung. . .
Gaoithe
1
Benötigen Sie zwei Dinge: 1. Wenn ein Container erstellt wird, verwenden Sie ein Init-Skript, um / etc / localtime symlink und / etc / timezone festzulegen Startet den Jenkins-Prozess. zB "-Dorg.apache.commons.jelly.tags.fmt.timeZone = America / New_York -Duser.timezone = America / New_York". Entschuldigung, dies ist Jenkins-spezifisch, aber hoffentlich nützlich für einige andere Jenkins-Benutzer.
Gaoithe

Antworten:

208

Das Geheimnis hierbei ist, dass man dpkg-reconfigure tzdataeinfach /etc/localtimeals Kopie, Hardlink oder Symlink (ein Symlink wird bevorzugt) eine Datei in erstellt /usr/share/zoneinfo. Es ist also möglich, dies vollständig von Ihrem Dockerfile aus zu tun. Erwägen:

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

Und als Bonus wird TZ auch im Container korrekt eingestellt.

Dies ist auch verteilungsunabhängig, so dass es mit so ziemlich jedem Linux funktioniert.

Hinweis: Wenn Sie ein alpines Image verwenden, müssen Sie das tzdataerste installieren . (siehe diese Ausgabe hier )

Sieht aus wie das:

RUN apk add --no-cache tzdata
ENV TZ America/Los_Angeles
Michael Hampton
quelle
5
Mit Ubuntu: 16.04 (und möglicherweise einer anderen Version) muss ein tzdataPaket installiert sein, damit dies funktioniert.
Opsse
5
Bin ich der einzige, der denkt, es sei nicht sehr klug, eine Zeitzone im Dockerfile fest zu codieren?
Wolfgang
1
@Wolfgang Dies ist ein Beispiel. Sie können es auf jede andere Art und Weise bereitstellen, die Sie normalerweise für Umgebungsvariablen verwenden, z. B. die Befehlszeile, docker-compose.yml usw.
Michael Hampton
Mir ist aufgefallen, dass es zumindest für alpine Bilder TZausreicht , nur die Variable zu setzen. Ich musste weder die Symlinks noch irgendetwas anderes einrichten.
Code_dredd
58

In der Regel ist es ausreichend, eine Umgebungsvariable im Docker-Container wie folgt festzulegen:

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

Das würde natürlich auch mit funktionieren docker-compose.

Victor Klos
quelle
2
Dies scheint der eleganteste Weg zu sein. Stellen Sie sicher, dass einige Basis-Images ubuntu:16.04nicht über das tzdataPaket verfügen, das in Dockerfile hinzugefügt werden soll.
Julien Fastré
1
+1 - Ich stimme Julien zu; Dies scheint der eleganteste Ansatz zum Festlegen von Zeitzonen zur Laufzeit zu sein. Dies funktioniert gut mit CentOS. Für Alpine-Images ist die Installation des Pakets 'tzdata' erforderlich, das zur Erstellungszeit Harcoding-Konfigurationen vorzuziehen ist, es sei denn, die zusätzlichen 3 MB Image-Nutzdaten können nicht toleriert werden :)
Frelling
Das scheint gut zu sein, scheint aber bei mir nicht zu funktionieren (mit CentOS 7.5.1804 und tzdata-2018e-3.el7.noarch)? trauriges Gesicht
Gaoithe
22

Das Einhängen /etc/localtimein das Bild, damit es synchron host -vist, ist das beliebteste.

Aber siehe Ausgabe 12084 :

Es ist nicht korrekt, da es nicht funktioniert, wenn die Software stattdessen die /etc/timezoneEinstellung der Datei erfordert .
Auf diese Weise wird der Standardwert beibehalten etc/UTC.

Ich habe festgestellt, dass es tatsächlich keine narrensichere und elegante Möglichkeit gibt, die Zeitzone in einem Docker-Container festzulegen.
Also habe mich endlich für diese Lösung entschieden:

App Dockerfile:

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

App-Einstiegspunkt-Skript:

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

Datenvolumen /configdockerfile, lokalisiert auf einem bestimmten Land oder Region:

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

... es ist nicht elegant, da es drei separate Dateien umfasst und /etc/localtimebei jedem Start des Laufzeitcontainers neu erstellt wird. Welches ist eher verschwenderisch.

Es funktioniert jedoch ordnungsgemäß und erzielt erfolgreich eine Trennung zwischen dem Basis-App-Image und jeder länderspezifischen lokalisierten Konfiguration.
In 3 Codezeilen.

VonC
quelle
1
Für mich war es: RUN echo "Europe/London" > /etc/timezone
jpmottin
@jpmottin Also ein bisschen wie in serverfault.com/a/856593/783 dann?
Vom
18

Sie können Ihre lokalen Dateien (/ etc / timezone und / etc / localtime) als Volume in Ihrem Docker-Container hinzufügen.

Aktualisieren Sie Ihre docker-compose.ymlmit den folgenden Zeilen.

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

Jetzt ist die Containerzeit dieselbe wie auf Ihrem Host

als
quelle
Wenn Sie einen CentOS Distributor haben, geben Sie den Befehl ein, echo "Europe/Paris" > /etc/timezonebevor Sie den Container neu starten.
CrazyMax
Funktioniert das auf MacOS-Hosts?
Redsandro
Funktioniert nicht in MAC
Marcello de Sales
Dies funktionierte früher unter MacOS, aber ich habe es erst nach langer Zeit wieder probiert und bekomme folgendes. Nicht sicher, ob High Sierra oder eine Docker-Änderung dies verursacht haben: "Docker: Fehlerantwort vom Daemon: Bereitstellungen verweigert: Der Pfad / etc / localtime wird von OS X nicht freigegeben und ist Docker nicht bekannt. Sie können freigegebene Pfade von Docker aus konfigurieren - > Einstellungen ... -> Dateifreigabe. Weitere Informationen finden Sie unter docs.docker.com/docker-for-mac/osxfs/#namespaces . "
gae123
1
Dadurch wird Ihre zoneinfo-Datenbank beschädigt, da / etc / localtime ein Symlink ist (daher wird / usr / share / zoneinfo / Some / Thing wahrscheinlich als / usr / share / zoneinfo / UTC im Container eingebunden). Ganz zu schweigen davon, dass Sie die Datenbankdatei vom Host mit der im Container mischen würden.
ionelmc
12

In Ubuntu 16.04 Bild gibt es Fehler. Lösung war

    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
QWERTY
quelle
1
Im Ernst ... das ist die einzige Lösung, die funktioniert hat!
Gerrat
1
Musste das auch machen - anscheinend ist tzdata in einigen Distributionen nicht mehr standardmäßig.
Peter
4

Wenn Sie ein Docker-Image verwenden, basierend auf ubuntu:

# Change the docker default timezone from UTC to SGT
echo "Asia/Singapore" > /etc/timezone
dpkg-reconfigure tzdata
date
Xianlin
quelle
3

Vielen Dank an VonC für die Informationen und den Link zum Thema. Dies scheint ein so verworrenes Durcheinander zu sein, dass ich meine eigene Idee getestet habe, wie man das löst, und es scheint großartig zu funktionieren.

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

(Folgen Sie den Anweisungen, um meine Zeitzone auszuwählen.)

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

Dann habe ich meine Dockerdateien aktualisiert, um dies widerzuspiegeln:

FROM chocko/ubuntu:local

Daran muss etwas falsch sein, denn es scheint zu leicht zu sein, übersehen zu werden ... Oder ist das akzeptabel?

Chockomonkey
quelle
Das habe ich auch versucht, aber die Zeitzone setzt sich immer noch von selbst zurück, nachdem ich exitden Container geöffnet habe . Dies ist auf Debian.
Mike Chamberlain
@MikeChamberlain hast du zufällig die akzeptierte Antwort von Michael Hampton oben ausprobiert? Ich habe es nicht selbst implementiert, aber ich denke, es ist der richtige Weg, wenn man die erhaltenen Upvotes berücksichtigt.
Chockomonkey
2

Fügen Sie hier meine zwei Cent hinzu, weil ich mehrere davon ausprobiert habe, aber keiner mit Bildern auf Alpinbasis gearbeitet hat.

Dies hat jedoch den Trick getan:

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/*

[ Quelle ]

Alpha
quelle
1

Eine allgemeinere Methode zum Festlegen der Zeitzone in docker runArgumenten:

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

Oder zur Wiederverwendung:

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

...
-e TZ=`GET_TZ`
Mugen
quelle
hilft nicht, wenn Ihr Basis-Image alpine (5 MB) ist, auf dem "tzdata" nicht installiert ist
max4ever