Zeitzonen in Docker-Container
Beim Auswerten der Logs diverser Docker-Container stieß ich auf ein Problem: Docker-Container hatten teilweise die lokale Zeitzone (CET
, die auch auf dem Host konfiguriert ist), teilweise UTC
-Zeit konfiguriert. Interessanterweise fand ich beim Debuggen noch eine weitere Zeitzone in einem anderen Docker-Container. Der Grund dafür: jeder Entwickler kann in seinem Dockerfile in 1 - 2 Zeilen Code eine beliebige Zeitzone setzen - was natürlich definitiv keine gute Praxis ist, aber dennoch in einem von mir verwendeten Container vorkam. Standard für die meisten Container ist übrigens UTC
.
$ docker run --rm debian date
Tue Mar 23 19:13:37 UTC 2021
Um alle Container nun zu normalisieren (und die Logs dann auch leichter verarbeiten zu können) hat sich bei mir eine Kombination aus zwei Maßnahmen bewiesen:
Zeitzone per /etc/localtime setzen
Der Symlink /etc/localtime
steuert in sämtlichen gängigen Linux-Distributionen die Zeitzone. Er verweist auf die entsprechende Datei unter /usr/share/zoneinfo
.
$ ls -lah /etc/localtime
lrwxrwxrwx 1 root root 33 Feb 4 20:23 /etc/localtime -> /usr/share/zoneinfo/Europe/Berlin
Der einfachste Weg um die korrekte Zeitzone in einem Docker-Container zu konfigurieren ist die Datei /etc/timezone
des Host-Systems zu mounten. Da der Container die Datei nicht ändern können soll, mounten wir sie einfach read-only.
$ docker run -v /etc/localtime:/etc/localtime:ro --rm debian date
Tue Mar 23 20:13:37 CET 2021
Die so gesetzte Zeitzone greift aber leider nicht für alle Anwendungen innerhalb eines des Docker-Containers:
$ docker run -v /etc/localtime:/etc/localtime:ro openjdk /bin/sh -c 'curl -s https://gist.githubusercontent.com/tldev-de/8a1c0247b59042dd4faa5c50b65d4754/raw/241697e9602ef79aac67a84b4594ef69290836c7/GetTimeZone.java > GetTimeZone.java && java GetTimeZone.java'
sun.util.calendar.ZoneInfo[id="GMT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
In diesem Minimalbeispiel downloaden wir eine Java-Klasse per wget
, welche wir anschließend innerhalb des openjdk
-Container ausführen. Als Zeitzone liefert uns Java GMT
statt CET
.
Zeitzone per Environment Variable setzen
Glücklicherweise gibt es einen weiteren Weg, wie wir die Zeitzone innerhalb eines Docker-Containers setzen können: die Environment-Variable TZ
. Je nach Docker-Container ersetzt die Verwendung der Environment-Variable auch das Mounten der /etc/localtime
: ist das Paket tzdata
installiert, genügt das Überschreiben durch die Environment-Variable.
$ docker run -e TZ=Europe/Berlin openjdk /bin/sh -c 'curl -s https://gist.githubusercontent.com/tldev-de/8a1c0247b59042dd4faa5c50b65d4754/raw/241697e9602ef79aac67a84b4594ef69290836c7/GetTimeZone.java > GetTimeZone.java && java GetTimeZone.java'
sun.util.calendar.ZoneInfo[id="Europe/Berlin",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=143,lastRule=java.util.SimpleTimeZone[id=Europe/Berlin,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]
Fazit
Ich für mich habe beschlossen den sicheren Weg zu ergreifen und beide Lösungen zu kombinieren. So habe ich bei allen meinen aktuell genutzten Containern die gleiche Zeitzone konfiguriert
$ docker run -e TZ=Europe/Berlin -v /etc/localtime:/etc/localtime:ro --rm debian date
Tue Mar 23 20:13:37 CET 2021
$ docker run -v /etc/localtime:/etc/localtime:ro -e TZ=Europe/Berlin openjdk /bin/sh -c 'curl -s https://gist.githubusercontent.com/tldev-de/8a1c0247b59042dd4faa5c50b65d4754/raw/241697e9602ef79aac67a84b4594ef69290836c7/GetTimeZone.java > GetTimeZone.java && java GetTimeZone.java'
sun.util.calendar.ZoneInfo[id="Europe/Berlin",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=143,lastRule=java.util.SimpleTimeZone[id=Europe/Berlin,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]