Docker Thời gian và múi giờ của Container (sẽ không phản ánh các thay đổi)


135

Nơi Docker container có được thông tin thời gian của họ? Tôi đã tạo một số container từ ubfox cơ bản: hình ảnh đáng tin cậy và khi tôi chạy nó và yêu cầu 'ngày', tôi nhận được thời gian UTC.

Trong một lúc, tôi đã khắc phục điều này bằng cách làm như sau trong Dockerfile của mình:

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

Tuy nhiên, vì một số lý do mà ngừng hoạt động. Tìm kiếm trực tuyến tôi thấy đề xuất dưới đây:

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

Cả hai phương pháp này đều đặt chính xác múi giờ!

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

Bất cứ ai biết những gì cho?


3
Nếu bạn sử dụng Alpine, bạn cần phải cài đặt tzdatađầu tiên, xem tại đây github.com/gliderlabs/docker-alpine/issues/136
Belter

1
FYI. . . Tôi muốn đặt múi giờ của container tại thời gian chạy docker chứ không phải tại docker build / dockerfile time. Sử dụng -v /etc/localtime:/etc/localtime:ro(CentOS) loại công việc. Bên trong ngày dòng lệnh container trả về ngày ở định dạng múi giờ dự kiến. NHƯNG jenkins chạy trong container nghĩ rằng múi giờ là UTC. Tại sao? / etc / localtime là một liên kết tượng trưng đến ../usr/share/zoneinfo/UTC trong vùng chứa được xây dựng. Nội dung của tệp UTC trong container hiện là múi giờ mới. Nhưng jenkins (và có lẽ các phần mềm dựa trên java khác) sử dụng tên của symlink vẫn là "UTC". Tìm kiếm giải pháp. . .
gaoithe

1
Cần 2 điều, 1. khi container được tạo, hãy sử dụng tập lệnh init để đặt / etc / symlink symlink và / etc / timezone và 2. cho múi giờ jenkins được lấy từ hai tùy chọn java, các tùy chọn này cần được chuyển đến tập lệnh init. bắt đầu quá trình jenkins. ví dụ: "-Dorg.apache.commons.jelly.tags.fmt.timeZone = America / New_York -Duser.timezone = America / New_York". Xin lỗi, đây là cụ thể của jenkins nhưng hy vọng hữu ích cho một số người dùng jenkins khác.
gaoithe

Câu trả lời:


208

Bí mật ở đây là dpkg-reconfigure tzdatachỉ cần tạo /etc/localtimemột bản sao, liên kết cứng hoặc liên kết tượng trưng (một liên kết tượng trưng được ưu tiên) cho một tệp trong /usr/share/zoneinfo. Vì vậy, có thể làm điều này hoàn toàn từ Dockerfile của bạn. Xem xét:

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

Và như một phần thưởng, TZ cũng sẽ được đặt chính xác trong container.

Đây cũng là bất khả tri phân phối, do đó, nó hoạt động với hầu hết mọi Linux.

Lưu ý: nếu bạn đang sử dụng hình ảnh dựa trên núi cao, bạn phải cài đặt hình ảnh tzdatađầu tiên. (xem vấn đề này ở đây )

Trông như thế này:

RUN apk add --no-cache tzdata
ENV TZ America/Los_Angeles


5
Với Ubuntu: 16.04 (và có thể là phiên bản khác), bạn cần tzdatacài đặt gói để thực hiện công việc này.
Opsse

5
Tôi có phải là người duy nhất nghĩ rằng việc mã hóa múi giờ trong Dockerfile không thông minh không?
Wolfgang

1
@Wolfgang Đây là một ví dụ. Bạn có thể cung cấp nó theo bất kỳ cách nào khác mà bạn thường cung cấp các biến môi trường, chẳng hạn như dòng lệnh, docker-compose.yml, v.v.
Michael Hampton

Tôi nhận thấy rằng, ít nhất là đối với các hình ảnh dựa trên Alps, chỉ cần đặt TZbiến là đủ. Tôi đã không phải thiết lập các liên kết tượng trưng hoặc bất cứ điều gì khác.
code_dredd

58

Thông thường chỉ cần đặt một biến môi trường trong bộ chứa docker là như vậy:

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

Tất nhiên điều này cũng sẽ làm việc với docker-compose.


2
Đây dường như là cách thanh lịch nhất. Cẩn thận rằng một số hình ảnh cơ bản, như ubuntu:16.04, không có tzdatagói cần được thêm vào Dockerfile.
Julien Fastré

1
+1 - Tôi đồng ý với Julien; đây dường như là cách tiếp cận thanh lịch nhất để thiết lập các múi giờ khi chạy. Điều này hoạt động tốt với CentOS. Hình ảnh Alps yêu cầu cài đặt gói 'tzdata', được ưu tiên hơn các cấu hình mã hóa tại thời điểm xây dựng trừ khi không thể chấp nhận tải trọng hình ảnh 3 MB thêm :)
Frelling 27/12/17

Điều này có vẻ tốt nhưng dường như không hoạt động đối với tôi (với CentOS 7.5.1804 và tzdata-2018e-3.el7.noarch)? khuôn mặt buồn
gaoithe

22

Gắn kết /etc/localtimetrong hình ảnh, vì vậy nó được đồng bộ hóa host -vlà phổ biến nhất.

Nhưng xem vấn đề 12084 :

nó không đúng bởi vì nó không hoạt động khi phần mềm yêu cầu thay vì tập tin /etc/timezoneđược đặt.
Bằng cách đó, bạn đang sử dụng lá nó làm giá trị mặc định etc/UTC.

Tôi đã xác định rằng thực sự không có cách nào tao nhã để đặt múi giờ bên trong một container docker.
Vì vậy, cuối cùng đã giải quyết về giải pháp này:

Ứng dụng dockerfile:

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

Kịch bản điểm vào ứng dụng:

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

/configDockerfile khối lượng dữ liệu , được bản địa hóa cho một quốc gia hoặc khu vực cụ thể:

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

... nó không thanh lịch vì liên quan đến 3 tệp riêng biệt và tạo lại /etc/localtimetrên mỗi lần khởi động bộ chứa thời gian chạy. Mà là khá lãng phí.

Tuy nhiên, nó hoạt động đúng và đạt được thành công tách biệt giữa hình ảnh ứng dụng cơ sở và từng cấu hình được bản địa hóa của mỗi quốc gia.
Trong 3 dòng mã.


1
Đối với tôi, đó là: RUN echo "Europe/London" > /etc/timezone
jpmottin

@jpmottin Vậy một chút như trong serverfault.com/a/856593/783 thì sao?
VonC

18

Bạn có thể thêm các tệp cục bộ của mình (/ etc / múi giờ và / etc / localtime) dưới dạng âm lượng trong bộ chứa docker của bạn.

Cập nhật của bạn docker-compose.ymlvới các dòng sau.

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

Bây giờ thời gian chứa giống như trên máy chủ của bạn


Nếu máy chủ phân phối CentOS của bạn nhập lệnh echo "Europe/Paris" > /etc/timezonetrước khi khởi động lại container.
CrazyMax

Điều này có hoạt động trên máy chủ MacOS không?
Redsandro

Không làm việc trong MAC
Marcello de Sales

Điều này được sử dụng để làm việc trên MacOS nhưng tôi đã thử lại sau một thời gian dài và tôi nhận được những điều sau đây. Không chắc chắn nếu High Sierra hoặc thay đổi docker gây ra điều này: "docker: Phản hồi lỗi từ daemon: Mounts bị từ chối: Đường dẫn / etc / localtime không được chia sẻ từ OS X và không được biết đến Docker. Bạn có thể định cấu hình các đường dẫn được chia sẻ từ Docker - > Tùy chọn ... -> Chia sẻ tệp. Xem docs.docker.com/docker-for-mac/osxfs/#namespaces để biết thêm thông tin. "
gae123

1
Điều này sẽ làm hỏng db vùnginfo của bạn vì / etc / localtime là một liên kết tượng trưng (do đó / usr / share / zoneinfo / Một số / Điều có thể được gắn kết là / usr / share / zoneinfo / UTC bên trong container). Chưa kể rằng bạn sẽ trộn tệp db từ máy chủ lưu trữ với tệp trong bộ chứa.
ionelmc

12

Trong hình ảnh Ubuntu 16.04 có lỗi. Giải pháp là

    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
Nghiêm túc ... đây là giải pháp duy nhất có hiệu quả!
Gerrat

1
Cũng phải làm điều này - có vẻ như tzdata không còn trong một số bản phát hành theo mặc định.
Peter

4

nếu bạn đang sử dụng hình ảnh docker dựa trên ubuntu:

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

3

Cảm ơn VonC về thông tin và liên kết đến vấn đề. Điều này có vẻ như là một mớ hỗn độn như vậy, vì vậy tôi đã thực hiện một số thử nghiệm trên ý tưởng của riêng tôi về cách giải quyết vấn đề này và nó dường như hoạt động rất tốt.

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

(làm theo lời nhắc để chọn múi giờ của tôi)

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

Sau đó, tôi đã cập nhật Dockerfiles của mình để phản ánh điều này:

FROM chocko/ubuntu:local

Có điều gì đó không ổn với điều này bởi vì nó dường như quá dễ bị bỏ qua ... Hay điều này có thể chấp nhận được?


Đây cũng là những gì tôi đã thử, nhưng múi giờ vẫn tự đặt lại sau khi tôi exitchứa. Đây là trên Debian.
Mike Chamberlain

@MikeChamberlain bạn có tình cờ thử câu trả lời được chấp nhận của Michael Hampton ở trên không? Tôi đã không tự mình thực hiện nó, nhưng tôi nghĩ đó là cách để xem xét các ưu đãi mà nó đã nhận được.
Chockomonkey

2

Thêm hai xu của tôi ở đây, bởi vì tôi đã thử một vài trong số này nhưng không có tác dụng nào trên các hình ảnh dựa trên núi cao.

Tuy nhiên, điều này đã lừa

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

[ Nguồn ]


1

Một cách chung hơn để đặt múi giờ trong các docker runđối số:

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

Hoặc để tái sử dụng:

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

...
-e TZ=`GET_TZ`

không giúp đỡ nếu hình ảnh cơ sở của bạn là alpine (5MB) không cài đặt "tzdata"
max4ever
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.