เวลาและเขตของ Docker Container (จะไม่สะท้อนการเปลี่ยนแปลง)


135

คอนเทนเนอร์ Docker จะรับข้อมูลเวลาได้ที่ไหน ฉันได้สร้างตู้คอนเทนเนอร์จากพื้นฐานอูบุนตู: ภาพที่น่าเชื่อถือและเมื่อฉันเรียกใช้และขอ 'วันที่' ฉันจะได้รับเวลา 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/issues/136
Belter

1
FYI . . ฉันต้องการตั้งค่าเขตเวลาของคอนเทนเนอร์ในเวลาทำงานของนักเทียบท่าไม่ใช่เวลาสร้าง / เทียบท่าที่นักเทียบท่า การใช้งาน-v /etc/localtime:/etc/localtime:roเรียงลำดับ (CentOS) ภายในวันที่บรรทัดคำสั่งของคอนเทนเนอร์ส่งคืนวันที่ในรูปแบบเขตเวลาที่คาดไว้ แต่เจนกินส์ที่ทำงานอยู่ในคอนเทนเนอร์คิดว่าเขตเวลาคือ UTC ทำไม? / etc / localtime เป็น symlink ไปที่ ../usr/share/zoneinfo/UTC ในคอนเทนเนอร์ที่สร้างขึ้น เนื้อหาของไฟล์ UTC ในคอนเทนเนอร์เป็นเขตเวลาใหม่แล้ว แต่เจนกินส์ (และอาจเป็นซอฟต์แวร์ที่ใช้จาวาอื่น ๆ ) ใช้ชื่อของ symlink ซึ่งยังคงเป็น "UTC" ค้นหาวิธีแก้ปัญหา . .
gaoithe

1
ต้องการ 2 สิ่ง 1. เมื่อสร้างคอนเทนเนอร์ใช้สคริปต์ init เพื่อตั้งค่า / etc / localtime symlink และ / etc / timezone และ 2. สำหรับเจนกินส์เขตเวลาถูกนำมาจากสองตัวเลือกจาวาตัวเลือกเหล่านี้จะต้องถูกส่งไปยังสคริปต์เริ่มต้นซึ่ง เริ่มกระบวนการเจนกินส์ เช่น "-Dorg.apache.commons.jelly.tags.fmt.timeZone = อเมริกา / New_York -Duser.timezone = อเมริกา / New_York" ขออภัยนี่คือเจนกินส์โดยเฉพาะ แต่หวังว่าจะเป็นประโยชน์สำหรับผู้ใช้เจนกินส์รายอื่น ๆ
gaoithe

คำตอบ:


208

ความลับที่นี่เป็นที่dpkg-reconfigure tzdataเพียงแค่สร้าง/etc/localtimeเป็นสำเนา, Hardlink หรือ symlink (ก symlink เป็นที่ต้องการ) /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แพ็คเกจที่ติดตั้งเพื่อใช้งานได้
Opsse

5
ฉันเป็นคนเดียวที่คิดว่าไม่ฉลาดในการ hardcode โซนเวลาใน Dockerfile หรือไม่?
Wolfgang

1
@ Wolfgang นี่เป็นตัวอย่าง คุณสามารถจัดเตรียมได้ในวิธีอื่น ๆ ที่คุณมักจะให้ตัวแปรสภาพแวดล้อมเช่นบรรทัดคำสั่ง docker-compose.yml ฯลฯ
Michael Hampton

ฉันสังเกตเห็นว่าอย่างน้อยที่สุดสำหรับภาพจากอัลไพน์เพียงแค่ตั้งค่าTZตัวแปรก็เพียงพอแล้ว ฉันไม่ต้องตั้งค่า symlink หรืออะไรอย่างอื่น
code_dredd

58

ปกติแล้วมันจะเพียงพอที่จะตั้งค่าตัวแปรสภาพแวดล้อมในคอนเทนเนอร์นักเทียบท่าเช่น:

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

docker-composeหลักสูตรนี้จะทำงานด้วย


2
นี่เป็นวิธีที่ดีที่สุด โปรดระวังว่าบางรูปพื้นฐานเช่นubuntu:16.04ไม่มีtzdataแพ็คเกจที่ควรเพิ่มใน Dockerfile
Julien Fastré

1
+1 - ฉันเห็นด้วยกับ Julien; นี่ดูเหมือนจะเป็นวิธีที่ยอดเยี่ยมที่สุดสำหรับการตั้งค่าโซนเวลาในขณะทำงาน ใช้งานได้ดีกับ CentOS ภาพอัลไพน์ไม่จำเป็นต้องติดตั้งแพคเกจ 'tzdata' ซึ่งเป็นที่ต้องการมากกว่าการกำหนดค่าการแฮร์คโค้ดในเวลาที่สร้างเว้นแต่ว่าจะไม่สามารถทนต่อการโหลดภาพขนาด 3MB เพิ่มเติม :)
Frelling

ดูเหมือนว่าจะดี แต่ดูเหมือนจะใช้ไม่ได้สำหรับฉัน (ด้วย CentOS 7.5.1804 และ tzdata-2018e-3.el7.noarch)? หน้าเศร้า
gaoithe

22

การติดตั้ง/etc/localtimeในภาพดังนั้นการซิงค์ด้วยhost -vจึงเป็นสิ่งที่ได้รับความนิยมมากที่สุด

แต่ดูปัญหา 12084 :

มันไม่ถูกต้องเพราะมันไม่ทำงานเมื่อซอฟต์แวร์ต้องการแทนไฟล์/etc/timezoneที่จะตั้งค่า วิธีการที่คุณกำลังใช้ใบมันเป็นค่าเริ่มต้น
etc/UTC

ฉันได้พิจารณาแล้วว่าจริง ๆ แล้วไม่มีวิธีที่จะเข้าใจผิดได้ในการตั้งเขตเวลาในคอนเทนเนอร์ของนักเทียบท่า
ดังนั้นจึงได้ตัดสินในโซลูชันนี้:

App 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

data /configdockerfile data ซึ่งแปลเป็นภาษาท้องถิ่นหรือภูมิภาคเฉพาะ:

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

... มันไม่สวยงามเพราะมี 3 ไฟล์แยกกันและการสร้างใหม่/etc/localtimeในทุกครั้งที่เริ่มรันไทม์คอนเทนเนอร์ ซึ่งค่อนข้างสิ้นเปลือง

อย่างไรก็ตามมันทำงานได้อย่างถูกต้องและประสบความสำเร็จในการแยกระหว่างอิมเมจแอพพื้นฐานและการกำหนดค่าที่แปลแต่ละประเทศ
ในรหัส 3 บรรทัด


1
สำหรับฉันมันคือ: RUN echo "Europe/London" > /etc/timezone
jpmottin

@jpmottin ถ้าอย่างนั้นก็เหมือนในserverfault.com/a/856593/783งั้นเหรอ?
VonC

18

คุณสามารถเพิ่มไฟล์โลคัลของคุณ (/ etc / timezone และ / etc / localtime) เป็นไดรฟ์ข้อมูลใน docker-container ของคุณ

อัพเดตของคุณdocker-compose.ymlด้วยบรรทัดต่อไปนี้

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

ขณะนี้เวลาคอนเทนเนอร์เหมือนกันกับโฮสต์ของคุณ


หากโฮสต์ CentOS distrib ของคุณป้อนคำสั่งecho "Europe/Paris" > /etc/timezoneก่อนที่จะรีสตาร์ทคอนเทนเนอร์
CrazyMax

ใช้งานได้กับโฮสต์ MacOS หรือไม่
Redsandro

ไม่ทำงานใน MAC
Marcello de Sales

สิ่งนี้เคยทำงานกับ MacOS แต่ฉันเพิ่งลองอีกครั้งหลังจากผ่านไปนานและฉันได้รับสิ่งต่อไปนี้ ไม่แน่ใจว่า High Sierra หรือการเปลี่ยนแปลง docker เป็นสาเหตุของสิ่งนี้หรือไม่: "นักเทียบท่า: การตอบสนองข้อผิดพลาดจาก daemon: การเมานต์ที่ถูกปฏิเสธ: เส้นทาง / etc / localtime ไม่ได้ถูกแชร์จาก OS X และไม่รู้จักกับ Docker คุณสามารถกำหนดค่าเส้นทางที่แชร์ > ค่ากำหนด ... -> การแชร์ไฟล์ดูdocs.docker.com/docker-for-mac/osxfs/#namespacesสำหรับข้อมูลเพิ่มเติม "
gae123

1
สิ่งนี้จะทำให้ db โซนของคุณเสียหายในขณะที่ / etc / localtime เป็น symlink (ดังนั้น / usr / share / zoneinfo / บางอย่างก็น่าจะถูกเมานต์เป็น / usr / share / zoneinfo / UTC ภายในคอนเทนเนอร์) ไม่ต้องพูดถึงว่าคุณจะผสมไฟล์ db จากโฮสต์กับไฟล์ในคอนเทนเนอร์
ionelmc

12

ในรูปอูบุนตู 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
อย่างจริงจัง ... นี่เป็นทางออกเดียวที่ได้ผล!
Gerrat

1
ต้องทำเช่นนี้ด้วย - ดูเหมือนว่า tzdata จะไม่อยู่ใน distros อีกต่อไป
ปีเตอร์

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
Mike Chamberlain

@MikeChamberlain คุณลองใช้คำตอบที่ได้รับการยอมรับโดย Michael Hampton ด้านบนหรือไม่ ฉันไม่ได้ใช้มันด้วยตัวเอง แต่ฉันคิดว่ามันเป็นวิธีที่จะไปพิจารณา upvotes ที่ได้รับ
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`

ไม่ช่วยถ้าภาพฐานของคุณเป็นอัลไพน์ (5MB) ซึ่งไม่มี "tzdata" ติดตั้ง
max4ever
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.