Docker Container time & timezone (tidak akan mencerminkan perubahan)

136

Di mana wadah Docker mendapatkan informasi waktunya? Saya telah membuat beberapa wadah dari ubuntu dasar: gambar tepercaya, dan ketika saya menjalankannya dan meminta 'tanggal', saya mendapatkan waktu UTC.

Untuk sementara saya menyelesaikan ini dengan melakukan hal berikut di Dockerfile saya:

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

Namun, untuk beberapa alasan yang berhenti bekerja. Pencarian online Saya melihat saran di bawah ini:

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

Kedua metode ini dengan benar mengatur zona waktu!

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

Adakah yang tahu apa yang terjadi?

Chockomonkey
sumber
3
Jika Anda menggunakan Alpine, Anda harus menginstal tzdataterlebih dahulu, lihat di sini github.com/gliderlabs/docker-alpine/issues/136
Belter
1
FYI. . . Saya ingin mengatur zona waktu kontainer pada waktu docker run bukan pada docker build / dockerfile. Menggunakan -v /etc/localtime:/etc/localtime:ro(CentOS) semacam karya. Tanggal baris perintah di dalam kontainer mengembalikan tanggal dalam format zona waktu yang diharapkan. TETAPI jenkins berjalan dalam wadah menganggap zona waktu adalah UTC. Mengapa? / etc / localtime adalah symlink ke ../usr/share/zoneinfo/UTC dalam wadah bawaan. Konten file UTC dalam wadah sekarang menjadi zona waktu baru. Tapi jenkins (dan mungkin perangkat lunak berbasis java lainnya) menggunakan nama symlink yang masih "UTC". Mencari solusi. . .
gaoithe
1
Perlu 2 hal, 1. ketika wadah dibuat menggunakan skrip init untuk mengatur / etc / localtime symlink dan / etc / timezone dan 2. untuk jenkins timezone diambil dari dua opsi java, opsi ini perlu diteruskan ke skrip init yang memulai proses jenkins. mis. "-Dorg.apache.commons.jelly.tags.fmt.timeZone = America / New_York -Duser.timezone = America / New_York". Maaf, ini spesifik untuk jenkins tapi mudah-mudahan bermanfaat untuk beberapa pengguna jenkins lainnya.
gaoithe

Jawaban:

209

Rahasianya di sini adalah bahwa dpkg-reconfigure tzdatacukup membuat /etc/localtimesebagai salinan, hardlink atau symlink (sebuah symlink lebih disukai) ke file di /usr/share/zoneinfo. Jadi dimungkinkan untuk melakukan ini sepenuhnya dari Dockerfile Anda. Mempertimbangkan:

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

Dan sebagai bonus, TZ akan diatur dengan benar dalam wadah juga.

Ini juga agnostik distribusi, sehingga berfungsi dengan hampir semua Linux.

Catatan: jika Anda menggunakan gambar berbasis alpine, Anda harus menginstal yang tzdatapertama. (lihat masalah ini di sini )

Terlihat seperti ini:

RUN apk add --no-cache tzdata
ENV TZ America/Los_Angeles
Michael Hampton
sumber
5
Dengan Ubuntu: 16.04 (dan mungkin versi lain), Anda perlu tzdatamenginstal paket untuk membuatnya berfungsi.
Opsse
5
Apakah saya satu-satunya yang berpikir bahwa tidak terlalu pintar untuk melakukan hardcode pada zona waktu di Dockerfile?
Wolfgang
1
@ Wolfgang Ini adalah contoh. Anda dapat menyediakannya dengan cara lain yang biasa Anda berikan variabel lingkungan, seperti baris perintah, docker-compose.yml, dll.
Michael Hampton
Saya perhatikan bahwa, setidaknya untuk gambar berbasis Alpine, hanya pengaturan TZvariabel sudah cukup. Saya tidak perlu mengatur symlink atau yang lainnya.
code_dredd
58

Biasanya cukup untuk menetapkan variabel lingkungan dalam wadah buruh pelabuhan, seperti:

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

Tentu saja ini akan berhasil juga docker-compose.

Victor Klos
sumber
2
Ini sepertinya cara yang paling elegan. Berhati-hatilah karena beberapa gambar dasar, seperti ubuntu:16.04, tidak memiliki tzdatapaket yang harus ditambahkan di Dockerfile.
Julien Fastré
1
+1 - Saya setuju dengan Julien; ini tampaknya menjadi pendekatan yang paling elegan untuk mengatur zona waktu saat runtime. Ini berfungsi baik dengan CentOS. Gambar Alpine memang membutuhkan instalasi paket 'tzdata', yang lebih disukai daripada konfigurasi harcoding saat membangun kecuali jika muatan gambar 3MB tambahan tidak dapat ditoleransi :)
Frelling
Ini sepertinya baik tetapi tampaknya tidak bekerja untuk saya (dengan CentOS 7.5.1804 dan tzdata-2018e-3.el7.noarch)? wajah sedih
gaoithe
22

Memasang /etc/localtimedi gambar, sehingga sinkron dengan host -vadalah yang paling populer.

Tapi lihat masalah 12084 :

itu tidak benar karena tidak berfungsi ketika perangkat lunak meminta sebaliknya file /etc/timezoneharus diatur.
Dengan cara itu Anda menggunakan menjadikannya sebagai nilai default etc/UTC.

Saya telah menentukan bahwa sebenarnya tidak ada cara elegan yang sangat mudah untuk mengatur zona waktu di dalam wadah buruh pelabuhan.
Jadi akhirnya memutuskan solusi ini:

Aplikasi dockerfile:

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

Skrip titik masuk aplikasi:

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

Volume data /configdockerfile, dilokalkan ke negara atau wilayah tertentu:

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

... itu tidak elegan karena melibatkan 3 file terpisah, dan membuat kembali /etc/localtimepada setiap awal runtime container. Yang agak boros.

Namun itu berfungsi dengan baik, dan berhasil mencapai pemisahan antara gambar aplikasi dasar, dan setiap konfigurasi lokal per-negara.
Dalam 3 baris kode.

VONC
sumber
1
Bagi saya, itu adalah: RUN echo "Europe/London" > /etc/timezone
jpmottin
@ jpmottin Jadi sedikit seperti di serverfault.com/a/856593/783 kalau begitu?
VonC
18

Anda dapat menambahkan file lokal Anda (/ etc / zona waktu dan / etc / localtime) sebagai volume di docker-container Anda.

Perbarui Anda docker-compose.ymldengan baris berikut.

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

Sekarang waktu penampungnya sama dengan tuan rumah Anda

dari
sumber
Jika host distribus CentOS Anda memasukkan perintah echo "Europe/Paris" > /etc/timezonesebelum memulai ulang wadah.
CrazyMax
Apakah ini berfungsi pada host MacOS?
Redsandro
Tidak BEKERJA di MAC
Marcello de Sales
Ini dulu berfungsi pada MacOS tapi saya baru mencobanya lagi setelah waktu yang lama dan saya mendapatkan yang berikut. Tidak yakin apakah High Sierra atau perubahan buruh pelabuhan menyebabkan ini: "buruh pelabuhan: Respons kesalahan dari daemon: Mounts ditolak: Jalur / etc / localtime tidak dibagi dari OS X dan tidak diketahui oleh Docker. Anda dapat mengonfigurasi jalur bersama dari Docker - > Preferensi ... -> Berbagi File. Lihat docs.docker.com/docker-for-mac/osxfs/#namespaces untuk info lebih lanjut. "
gae123
1
Ini akan merusak dz zoneinfo Anda karena / etc / localtime adalah symlink (dengan demikian / usr / share / zoneinfo / Some / Thing cenderung dipasang sebagai / usr / share / zoneinfo / UTC di dalam wadah). Belum lagi Anda akan mencampur file db dari host dengan yang ada di wadah.
ionelmc
12

Di ubuntu 16.04 gambar ada bug. Solusi tadinya

    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
sumber
1
Serius ... ini adalah satu-satunya solusi yang berhasil!
Gerrat
1
Juga harus melakukan ini - tampaknya tzdata tidak lagi dalam beberapa distro secara default.
Peter
4

jika Anda menggunakan gambar buruh pelabuhan berdasarkan ubuntu:

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

Terima kasih kepada VonC untuk informasi dan tautan ke masalah ini. Ini kelihatan seperti kekacauan yang berbelit-belit, jadi saya melakukan beberapa pengujian pada ide saya sendiri tentang bagaimana menyelesaikan ini dan tampaknya bekerja dengan baik.

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

(ikuti petunjuk untuk memilih zona waktu saya)

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

Kemudian saya memperbarui Dockerfiles saya untuk mencerminkan ini:

FROM chocko/ubuntu:local

Pasti ada yang salah dengan ini karena sepertinya terlalu mudah untuk dilupakan ... Atau apakah ini dapat diterima?

Chockomonkey
sumber
Ini juga yang saya coba, tetapi zona waktu masih me-reset sendiri setelah saya exitwadah. Ini di Debian.
Mike Chamberlain
@MikeChamberlain apakah Anda kebetulan mencoba jawaban yang diterima oleh Michael Hampton di atas? Saya belum menerapkannya sendiri, tetapi saya rasa ini adalah cara untuk mempertimbangkan upvotes yang telah diterima.
Chockomonkey
2

Menambahkan dua sen saya di sini, karena saya sudah mencoba beberapa di antaranya tetapi tidak ada yang bekerja pada gambar berbasis alpine.

Namun, ini berhasil:

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

[ Sumber ]

Alfa
sumber
1

Cara yang lebih umum untuk menetapkan zona waktu dalam docker runargumen:

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

Atau untuk digunakan kembali:

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

...
-e TZ=`GET_TZ`
Mugen
sumber
tidak membantu jika gambar dasar Anda adalah alpine (5MB) yang tidak memiliki "tzdata" terpasang
max4ever