วิธีการตั้งค่าเวลาของระบบแบบไดนามิกในคอนเทนเนอร์ Docker


28

มีวิธีใดบ้างที่จะตั้งเวลาของระบบ Docker container แบบไดนามิก (ณ รันไทม์) โดยไม่มีผลกระทบกับเครื่องโฮสต์?

การใช้

hwclock --set --date "Sat Aug 17 08:31:24 PDT 2016"

ให้ข้อผิดพลาดต่อไปนี้:

hwclock: Cannot access the Hardware Clock via any known method.
hwclock: Use the --debug option to see the details of our search for an access method.

การใช้

date -s "2 OCT 2006 18:00:00"

ให้ข้อผิดพลาดต่อไปนี้:

date: cannot set date: Operation not permitted

ใช้กรณี:

ฉันต้องทดสอบซอฟต์แวร์ที่มีความสำคัญต่อเวลา (พฤติกรรมขึ้นอยู่กับวันที่)

กรณีการใช้งานทั่วไปอื่น ๆ :

  • ใช้งานซอฟต์แวร์รุ่นเก่าที่มีข้อบกพร่อง y2k
  • ซอฟต์แวร์ทดสอบสำหรับการปฏิบัติตามปีพ
  • การดีบักปัญหาเกี่ยวกับเวลาเช่นใบรับรอง SSL ที่หมดอายุ
  • การใช้งานซอฟต์แวร์ซึ่งสิ้นสุดสภาพการทำงานนอกเวลาที่กำหนด
  • กระบวนการสร้างแบบกำหนดขึ้นเอง

อะไรคือจุดประสงค์ในการทำเช่นนั้น? คุณใช้กรณีอะไร
dawud

โปรดดูการแก้ไข
Vingtoft


1
ที่จริงฉันเพิ่งค้นพบและทดสอบวิธีแก้ปัญหาในเชิงบวกโดยใช้ libfaketime github.com/wolfcw/libfaketimeฉันจะอัปเดตด้วยคำตอบ + ตัวอย่างการทำงานในไม่ช้า
Vingtoft

คำตอบ:


21

มันเป็นไปได้

ทางออกคือการปลอมในภาชนะ lib นี้ขัดขวางโปรแกรมการเรียกใช้ระบบทั้งหมดที่ใช้เพื่อดึงข้อมูลเวลาและวันที่ปัจจุบัน

การติดตั้งใช้งานง่าย เพิ่มฟังก์ชันการทำงานให้กับ Dockerfile ของคุณตามความเหมาะสม:

WORKDIR /
RUN git clone https://github.com/wolfcw/libfaketime.git
WORKDIR /libfaketime/src
RUN make install

อย่าลืมตั้งค่าตัวแปรสภาพแวดล้อมLD_PRELOADก่อนที่คุณจะเรียกใช้แอพพลิเคชั่นที่คุณต้องการให้เวลาที่นำไปใช้

ตัวอย่าง:

CMD ["/bin/sh", "-c", "LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1 FAKETIME_NO_CACHE=1 python /srv/intercept/manage.py runserver 0.0.0.0:3000]

ตอนนี้คุณสามารถเปลี่ยนเวลาเซิร์ฟเวอร์แบบไดนามิก:

ตัวอย่าง:

import os
def set_time(request):
    print(datetime.today())
    os.environ["FAKETIME"] = "2020-01-01"  # Note: time of type string must be in the format "YYYY-MM-DD hh:mm:ss" or "+15d"
    print(datetime.today())

6
สำหรับผู้อื่นที่มาใช้วิธีนี้โปรดทราบว่าวิธีนี้จะไม่สามารถใช้ได้กับแอปพลิเคชัน golang หรือ exes ที่เชื่อมโยงแบบคงที่อื่น ๆ
Sentinel

5
ขอบคุณ @Sentinel สนุกมากฉันเพิ่งพบคำตอบนี้ผ่านทาง Google ฉันต้องการใช้มันกับแอป golang โดยเฉพาะและฉันสังเกตเห็นว่าคุณทิ้งความคิดเห็นนี้ไว้ในคำถามอายุ 1.5 ปีเพียง 2 ชั่วโมงที่ผ่านมา รู้สึกเหมือนเป็นฉัน ขอบคุณ! :)
dimonomid

เหตุใดจึงไม่ทำงานในสถานการณ์ของคุณ Golang ไม่ใช้การเรียกของระบบเพื่อดึงเวลาหรือไม่? @dimonomid ฉันขอแนะนำให้คุณลองใช้งานได้อย่างรวดเร็ว
Vingtoft

1
@Vingtoft ให้ฉันรู้ว่ามันใช้งานได้จริงหรือเปล่า Golang ไม่ได้ลิงก์แบบไดนามิกในห้องสมุด
Sentinel

1
@dimonomid ใช่ฉันค่อนข้างผิดหวัง ผิดหวังมากขึ้นกับนักเทียบท่าจริง ฉันต้องใช้การทดสอบที่เกี่ยวข้องกับเวลา สิ่งนี้ทำให้นักเทียบท่าไร้ประโยชน์อย่างมากในฐานะ "คอนเทนเนอร์" ฉันคิดว่าการสกัดกั้นเวลาของระบบจะทำให้การซิงค์เขตเวลาเป็นรายการที่ 1 ในวาระของนักเทียบท่า ชัดเจนว่าไม่.
Sentinel

4

Jenny D ถูกต้องแล้วโดยค่าเริ่มต้นคอนเทนเนอร์ Docker ไม่อนุญาตให้เข้าถึงนาฬิการะบบ

อย่างไรก็ตามสำหรับ Linux หากคุณใช้งานคอนเทนเนอร์ได้ดีคุณสามารถอนุญาตให้ใช้ความสามารถนี้ได้โดยใช้ตัวเลือก "--cap-add = SYS_TIME" ของคำสั่ง "docker run" เมื่อสร้างคอนเทนเนอร์ของคุณ:

# docker run --cap-add=SYS_TIME -d --name teamcity-server-instance -v /opt/teamcity/data:/data/teamcity_server/datadir -v /opt/teamcity/logs:/opt/teamcity/logs -p 80:8111 jetbrains/teamcity-server

จากนั้นคุณสามารถเปลี่ยนเวลาจากภายในคอนเทนเนอร์ที่ทำงาน:

# docker exec -it teamcity-server-instance /bin/bash
# date +%T -s "15:03:00"
15:03:00
#

เอกสารอ้างอิง: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities


2
สิ่งนี้จะเปลี่ยนเวลาบนเครื่องโฮสต์ เวลาบนระบบ Linux ไม่ได้ถูกกำหนดเนมสเปซในปัจจุบันมีเพียงค่าเดียวสำหรับโฮสต์และคอนเทนเนอร์ทั้งหมด
BMitch

ใช่คุณพูดถูก. สิ่งนี้จะเปลี่ยนเวลาของนาฬิกาเครื่องโฮสต์ เพียงแค่อ่านคำถามอีกครั้งและรับรู้คำถามจริงๆแล้วพูดถึงอย่างชัดเจนเกี่ยวกับการไม่เปลี่ยนนาฬิกาของเครื่องโฮสต์ ฉันยืนแก้ไข :)
Oleg Kazakov

0

สตาร์ทคอนเทนเนอร์ด้วยตัวแปรสภาวะแวดล้อมเพิ่มเติม:

docker run -e "SET_CONTAINER_TIMEZONE=true" \
           -e "CONTAINER_TIMEZONE=US/Arizona" [docker image name]

ฉันกำลังมองหาวิธีการตั้งเวลาแบบไดนามิกซึ่งหมายความว่ามันสามารถตั้งค่าได้ที่รันไทม์ ฉันได้อัปเดตคำถามของฉันแล้ว
Vingtoft

0

วิธีแก้ปัญหานักเทียบท่า:

เพิ่ม/etc/localtime:/etc/localtime:roไปยังvolumesแอตทริบิวต์

ดูที่ลิงค์นี้สำหรับตัวอย่าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.