2 คะแนน โดย GN⁺ 2025-03-25 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เนื่องจาก Podman ไม่มี daemon จึงต้องมีตัวดำเนินการที่จะยกคอนเทนเนอร์ขึ้นมาได้อย่างเสถียรหลังเซิร์ฟเวอร์บูต และ Quadlet แก้ปัญหานี้ด้วยแนวทางแบบไฟล์บริการของ systemd
  • เดิมที podman generate systemd ต้องจัดการการสร้างคอนเทนเนอร์และการสร้างไฟล์บริการแยกกัน และทุกครั้งที่ต้องเปลี่ยนไฟล์ที่สร้างขึ้นก็มีภาระในการ แก้ไขด้วยมือ
  • Quadlet วางการตั้งค่า [Container], [Service], [Install] ไว้ร่วมกันในไฟล์ .container ภายใต้ ~/.config/containers/systemd ทำให้จัดการตัวเลือกของ Podman และพฤติกรรมของ systemd ได้ในที่เดียว
  • สำหรับ rootless Podman การเริ่มอัตโนมัติตอนบูตต้องใช้ WantedBy=default.target และต้อง เปิดใช้งาน linger ส่วน multi-user.target ไม่ได้ถูกกำหนดไว้ในโหมดผู้ใช้
  • เมื่อใช้ AutoUpdate=registry, dependency ของ systemd, การจัดกลุ่มไฟล์ตามไดเรกทอรี และเครื่องมือแปลง podlet ร่วมกัน Quadlet จึงเหมาะกับการดำเนินงาน Podman แบบ rootless·daemonless

ทำไมจึงต้องมี Quadlet

  • Quadlet คือวิธีที่ทำให้รันคอนเทนเนอร์ Podman ได้เหมือนบริการของ systemd
    • สามารถรันคอนเทนเนอร์ในเบื้องหลังได้
    • สามารถเริ่มคอนเทนเนอร์อัตโนมัติหลังเซิร์ฟเวอร์รีบูตได้
  • แนวทางการรันคอนเทนเนอร์ Podman ภายใต้ systemd เองไม่ใช่เรื่องใหม่
    • เดิมใช้คำสั่ง podman generate systemd
    • ตอนนี้คำสั่งนี้แสดง คำเตือนว่าเลิกใช้แล้ว และแนะนำให้ย้ายไปใช้ Quadlet
  • Podman มีโครงสร้างแบบ daemonless ดังนั้นจึงต้องมีตัวดำเนินการที่จะเริ่มคอนเทนเนอร์ให้โดยไม่ต้องมี daemon

ความไม่สะดวกของวิธีเดิม podman generate systemd

  • วิธีเก่าต้องสร้างคอนเทนเนอร์ด้วย podman create ก่อน
    • คอนเทนเนอร์ตัวอย่างใช้ image docker.io/library/postgres:16
    • รวม -p 5432:5432, การเมานต์ volume, ตัวแปรสภาพแวดล้อม POSTGRES_PASSWORD และ label io.containers.autoupdate=registry
  • จากนั้นรัน podman generate systemd test-db -fn --new เพื่อสร้างไฟล์ container-test-db.service
  • ไฟล์บริการที่สร้างขึ้นถูกวางไว้ที่ ~/.config/systemd/user แล้วเปิดใช้งานและเริ่มด้วยคำสั่งต่อไปนี้
    • systemctl --user enable --now container-test-db
  • flow นี้ทำให้ต้องทำซ้ำขั้นตอนการสร้างคอนเทนเนอร์ สร้างไฟล์บริการ ย้ายไฟล์เมื่อจำเป็น และเปิดใช้งานบริการ
  • เมื่อคำสั่งสร้างคอนเทนเนอร์ยาวขึ้น ก็ต้องจัดการ shell script แยกต่างหากเพื่อให้รันซ้ำในภายหลังได้
  • หากต้องการปรับแต่งไฟล์บริการ systemd ที่สร้างขึ้น ก็ต้อง แก้ไขด้วยมือ ใหม่ทุกครั้ง

โครงสร้างไฟล์ Quadlet

  • ในแนวทาง Quadlet ให้สร้างไดเรกทอรี ~/.config/containers/systemd แล้ววางไฟล์ .container ไว้ข้างใน
  • ไฟล์ตัวอย่าง test-db.container มีองค์ประกอบต่อไปนี้
    • [Container]
      • Image=docker.io/library/postgres:16
      • AutoUpdate=registry
      • PublishPort=5432:5432
      • Volume=%h/volumes/test-db:/var/lib/postgresql/data:Z
      • Environment=POSTGRES_PASSWORD=CHANGE_ME
    • [Service]
      • Restart=always
    • [Install]
      • WantedBy=default.target
  • ไฟล์ .container เป็นไฟล์บริการ systemd ทั่วไป แต่มีส่วนพิเศษ [Container] รวมอยู่ด้วย
  • หลายตัวเลือกใน [Container] สอดคล้องกับตัวเลือกบรรทัดคำสั่งที่ใช้ใน podman create
    • Image: image และ tag ที่จะใช้
    • AutoUpdate=registry: สอดคล้องกับ --label "io.containers.autoupdate=registry"
    • PublishPort: สอดคล้องกับ -p
    • Volume: สอดคล้องกับ -v
    • Environment: สอดคล้องกับ -e
  • สำหรับไดเรกทอรี home ของผู้ใช้ ต้องใช้ตัวระบุของ systemd คือ %h แทน ~
  • Restart=always ใน [Service] ทำให้คอนเทนเนอร์รีสตาร์ตเสมอ เว้นแต่จะหยุดด้วยมือ
  • WantedBy=default.target ใน [Install] ทำให้คอนเทนเนอร์เริ่มอัตโนมัติเมื่อบูต

การตั้งค่า systemd ที่จำเป็นสำหรับ rootless Podman

  • สำหรับคอนเทนเนอร์แบบ rootless ต้องใช้ default.target ไม่ใช่ multi-user.target
    • multi-user.target ไม่ได้ถูกกำหนดไว้ในโหมดผู้ใช้ของ systemd
    • ตรวจสอบได้ด้วย systemctl --user status multi-user.target
    • ในโหมดระบบตรวจสอบได้ด้วย systemctl status multi-user.target
  • เนื่องจากรันคอนเทนเนอร์เป็นบริการผู้ใช้ของ systemd หากต้องการให้คอนเทนเนอร์เริ่มแม้ผู้ใช้ไม่ได้ login ต้องเปิดใช้งาน linger
    • loginctl enable-linger
  • หากต้องการเริ่มอัตโนมัติหลังเซิร์ฟเวอร์รีบูต การเปิดใช้งาน linger เป็นสิ่งจำเป็น
  • เพื่อให้ systemd พบไฟล์บริการใหม่ ให้รันคำสั่งต่อไปนี้
    • systemctl --user daemon-reload
  • การเริ่มคอนเทนเนอร์และตรวจสอบสถานะทำได้ทั้งฝั่ง systemd และ Podman
    • systemctl --user start test-db
    • systemctl --user status test-db
    • podman ps
  • ชื่อคอนเทนเนอร์เริ่มต้นคือรูปแบบที่เติม systemd- หน้าชื่อไฟล์บริการ
    • ชื่อคอนเทนเนอร์เริ่มต้นของ test-db.container คือ systemd-test-db
    • เป็นกฎการตั้งชื่อเพื่อหลีกเลี่ยงการชนกัน
    • สามารถกำหนดเองได้ด้วยตัวเลือก ContainerName ในส่วน [Container]

ข้อดีด้านการดำเนินงานของ Quadlet

  • Quadlet ทำให้จัดการการตั้งค่าบริการคอนเทนเนอร์ได้ด้วยไฟล์เดียว
    • ไม่จำเป็นต้องจัดการสคริปต์ที่สร้างไฟล์บริการและไฟล์บริการที่ถูกสร้างขึ้นแยกกันเหมือนวิธีเดิม
  • สามารถใช้ตัวเลือกที่มีในส่วน [Unit] และ [Service] ของ systemd ได้
    • เช่น ระบุคำสั่งที่จะรันก่อนเริ่มคอนเทนเนอร์ด้วย StartExecPre
    • ลดขั้นตอนการแก้ไฟล์ที่สร้างขึ้นด้วยมือในภายหลัง
  • แทนที่จะเขียนและ debug shell script ก็สามารถดำเนินงานคอนเทนเนอร์โดยยึด ไฟล์ configuration เป็นศูนย์กลางได้
  • แสดง dependency ระหว่างคอนเทนเนอร์ตามแนวทางของ systemd ได้ง่าย

การแสดง dependency ระหว่างคอนเทนเนอร์

  • หากคอนเทนเนอร์แอปพึ่งพาคอนเทนเนอร์ฐานข้อมูล สามารถกำหนดความสัมพันธ์ด้วยส่วน [Unit] ของ systemd ได้
  • คอนเทนเนอร์ OxiTraffic เป็นตัวอย่างที่พึ่งพาคอนเทนเนอร์ test-db
    • ตั้ง Requires=test-db.service ใน [Unit] เพื่อให้แอปเริ่มได้เฉพาะเมื่อฐานข้อมูลเริ่มแล้ว
    • ตั้ง After=test-db.service เพื่อไม่ให้คอนเทนเนอร์ทั้งสองเริ่มแบบขนานกัน
  • เวลาจะอ้างอิง ให้ใช้ ชื่อบริการ ไม่ใช่ชื่อไฟล์ .container
    • test-db.container: ชื่อไฟล์
    • test-db.service: ชื่อบริการ
    • systemd-test-db: ชื่อคอนเทนเนอร์เริ่มต้น
  • หากแอปต้องสื่อสารกับฐานข้อมูล ทั้งสองคอนเทนเนอร์ต้องเพิ่มตัวเลือก Network ในส่วน [Container] แต่จะไม่กล่าวถึง networking ในที่นี้

หลายไฟล์และการจัดกลุ่ม

  • Quadlet สามารถจัดโครงสร้างโดยแยกไฟล์ .container สำหรับแต่ละคอนเทนเนอร์ได้
  • เมื่อเทียบกับการใส่แอปหลายคอนเทนเนอร์ทั้งหมดไว้ในไฟล์ Docker Compose ไฟล์เดียว ไฟล์แยกตามคอนเทนเนอร์สามารถลด ภาระทางการรับรู้ ได้
  • หากไฟล์ Docker Compose มีหลายร้อยบรรทัดและคอนเทนเนอร์หลายสิบตัว การดูแลรักษาอาจยากขึ้น
  • Docker Compose ก็รองรับความสามารถในการแยกเป็นหลายไฟล์เช่นกัน
  • Quadlet สามารถวางไฟล์ unit ไว้ในไดเรกทอรีภายใต้ ~/.config/containers/systemd ได้
    • ในตัวอย่างสามารถสร้างไดเรกทอรี oxitraffic แล้ววางไฟล์ของแอปและฐานข้อมูลไว้ด้วยกันได้

การอัปเดต image

  • เมื่อตั้ง AutoUpdate=registry สามารถตรวจสอบการอัปเดต image ด้วย podman auto-update ได้
  • หากมี image ใหม่ที่เข้ากันได้กับ tag ที่ใช้อยู่ใน registry Podman จะ pull image แล้วรีสตาร์ตคอนเทนเนอร์
  • ใน Docker อาจต้องใช้เครื่องมืออย่าง Watchtower เพื่อวัตถุประสงค์นี้ แต่ Podman มีฟีเจอร์ดังกล่าวมาให้ในตัว
  • tag อย่าง latest อาจมีความเสี่ยง
    • ใน OxiTraffic latest อาจรวม breaking change ของเวอร์ชันถัดไป
    • หากใช้ latest กับ PostgreSQL อาจขยับขึ้นเป็น major version ใหม่ และการอัปเกรด major ของ PostgreSQL จำเป็นต้องมีการ migrate ด้วยมือเสมอ
  • ใน production ควรใช้ tag ที่ไม่นำไปสู่ breaking change
  • อีกวิธีหนึ่งคือรัน podman auto-update ด้วยมือทุก ๆ สองสามวันเพื่อดูว่ามีอะไรถูกอัปเดตบ้าง แล้วตรวจสอบภายหลังว่าคอนเทนเนอร์ทำงานปกติหรือไม่

podman-compose และเครื่องมือ migration

  • podman-compose เป็นสคริปต์ Python ที่รันไฟล์ Compose ด้วย Podman
  • เหตุผลที่มองว่าเป็นทางเลือกของ Docker Compose ในระยะยาวได้ยากมีดังนี้
    • เป็นชั้นการแปลระหว่างสเปก Compose กับ Podman·systemd และไม่ได้ทำให้ใช้ฟีเจอร์ทั้งหมดของ systemd ได้
    • โปรเจกต์ Podman ทางการเขียนด้วยภาษาคอมไพล์อย่าง Rust หรือ Go
    • commit ล่าสุดเมื่อ 5 เดือนก่อน จึงไม่ได้ถูกดูแลอย่างคึกคัก
  • Quadlet เข้ากับการออกแบบแบบ rootless·daemonless ของ Podman ได้ดีกว่า
  • หากต้องการลอง Quadlet จากไฟล์ Compose สามารถใช้ podlet ได้
    • เป็นเครื่องมือ Rust ที่สร้างไฟล์ Quadlet จากคำสั่ง Podman หรือไฟล์ Docker Compose ได้

อ่านเพิ่มเติม

  • หากต้องการเข้าใจ Quadlet ให้ลึกขึ้น man page podman-systemd.unit มีประโยชน์
  • Quadlet จัดการได้ไม่เฉพาะคอนเทนเนอร์ แต่ยังรวมถึง pod, network และ volume ด้วย
  • หากไม่คุ้นเคยกับการเขียนไฟล์ systemd unit สามารถดู man page systemd.unit และ systemd.service ได้
  • มุมมองอื่นและตัวอย่างที่สองดูได้จาก บทความคล้ายกันของ blog.while-true-do

1 ความคิดเห็น

 
GN⁺ 2025-03-25
ความคิดเห็นจาก Hacker News
  • Quadlet แทบจะเป็นสิ่งที่ดีที่สุดที่ออกมาจาก Podman และแนะนำอย่างมากสำหรับคนที่สนใจ Podman หรือกำลังจะย้ายไปใช้เวิร์กโหลดแบบคอนเทนเนอร์
    มันทำให้จัดการคอนเทนเนอร์ได้เหมือนเป็นบริการระบบทั่วไป โดยไม่ต้องไปเรียนรู้ออร์เคสเตรชันอีกชั้นเพื่อให้มันทำงานร่วมกัน หรือพึ่งพาทรัพยากรที่ไม่ใช่คอนเทนเนอร์
    แค่เขียน systemd unit แบบที่เคยใช้อยู่ได้เลย และยังได้การอัปเดตอัตโนมัติหรือการรีสตาร์ต/แจ้งเตือนเมื่อบริการล้มเป็นของแถม
    วิธีที่เคยพยายามทำอะไรคล้ายกันด้วย Docker มักจะลงเอยด้วยการเลี่ยง Docker daemon ผ่านคำสั่ง run ขนาดมหึมา จนเหลือบริการและคอนเทนเนอร์ผีไว้บ่อย ๆ แต่ Quadlet สะอาดกว่ามาก และคอนฟิกก็อยู่รวมกับตำแหน่งของ systemd unit อย่าง /etc/systemd/, .config/systemd, /usr/local/lib/systemd ทำให้สำรองข้อมูลง่าย
    แต่ก็ไม่ใช่คำตอบของ docker-compose สำหรับงานพัฒนาในเครื่อง และทีม Podman เองก็ดูไม่ได้สนใจพื้นที่นี้มากนัก
    คอนเทนเนอร์ฝั่งผู้ใช้เหมาะกับโครงสร้างพื้นฐานทดสอบในเครื่องที่รันยาว ๆ เช่นฐานข้อมูลเบื้องหลัง แต่สำหรับลูปทั่วไปแบบคอมไพล์ → docker compose up → ทดสอบ → docker compose down มันยุ่งยากเกินไป
    คำตอบที่ใช้งานได้จริงคือใช้ .kube Quadlet (Kubernetes play) หรือใช้ docker compose กับ Podman socket
    ชอบมันมากจนถึงขั้นใช้เวลาว่างหลายเดือนทำเครื่องมือ GitOps สำหรับจัดการ Quadlet และรู้สึกว่านี่คือวิธีที่ถูกต้องในการดูแลเซิร์ฟเวอร์ที่ทำงานแบบคอนเทนเนอร์
    สิ่งสำคัญคือ [0] ไม่ใช่ podman-compose ด้วย ผู้เขียนก็ชี้ไว้ในบทความเหมือนกันว่า podman-compose ไม่ค่อยดีและพัฒนาไม่มากพอ Podman รองรับ compose spec เกือบทั้งหมด จึงใช้ docker compose ได้ในแทบทุกสถานการณ์
    มีความเป็นไปได้สูงว่าคนที่ลองใช้ตอน RH เริ่มผลักดัน Podman ใหม่ ๆ จะเลิกใช้ไปเพราะความก้ำกึ่งของ Podman 3 และประสบการณ์แย่ ๆ กับ podman-compose

    • ผมอยากเดินไปในแนวทางของ RH มากขึ้นเลยลองใช้ Quadlet กับ podlet แต่ประสบการณ์ย้ายจาก docker compose บน Podman นั้นแย่มาก
      ต้องคอยเปลี่ยนแฟลก อัปเกรดเวอร์ชัน และไล่ตามกระแสที่แม้แต่ podlet เองยังแนะนำให้เปลี่ยนไปใช้เครื่องมืออื่น จนกลายเป็นโพรงกระต่ายไม่รู้จบ
      สุดท้าย systemd ของผมก็แค่รัน podman compose up
      เลยสงสัยว่าข้อดีของ Quadlet เมื่อเทียบกับการปล่อยให้ compose ทำหน้าที่ของมันเองคืออะไร
      สำหรับอ้างอิง Podman ของผมรันภายใต้ผู้ใช้ของผมเอง และไม่มี daemon เลย
    • เคล็ดลับสำหรับงานพัฒนาคือเปิด Podman socket และถ้าเป็นคอนเทนเนอร์แบบ rootless ก็ให้เปิดในระดับผู้ใช้ จากนั้นใช้ docker-compose แบบสแตนด์อโลน
    • บน Windows หรือ Mac ใช้ systemd ไม่ได้ สุดท้ายก็เหลือแค่ podman compose
  • เพิ่งค้นพบ Quadlet ไม่นานนี้ และได้สร้างโฮมแล็บทั้งชุดบนพื้นฐาน atomic OS กับ rootless Quadlet ซึ่งขอแนะนำอย่างมาก
    มันรองรับ systemd socket activation ได้ด้วย เช่นสามารถสร้าง systemd http/https socket แล้วให้ Traefik ถูกเปิดใช้งานอัตโนมัติได้ เหมือนกับที่ ssh.socket และ podman.socket เปิดใช้งาน sshd.service กับ podman.service ตามลำดับ
    สำหรับคอนฟิกแบบ rootless นี่แทบเป็นวิธีเดียวที่ใช้งานได้จริงในการคงค่า IP ต้นทางไว้ จนแทบเรียกว่าเป็นผู้ช่วยชีวิตได้เลย เพราะ rootless Podman/Docker โดยทั่วไปไม่ได้เปิดทางให้คงค่า IP ต้นทางได้ง่าย ๆ โดยไม่มีข้อเสียใหญ่
    https://github.com/savely-krasovsky/homelab

    • อยากรู้ว่าการเปิดใช้งาน Traefik ใช้เวลานานแค่ไหน
  • Quadlet เป็นทางเลือกที่ดีสำหรับการใช้งานแบบ docker compose ที่ว่า “รันคอนเทนเนอร์ที่พึ่งพากันทั้งหมดในสภาพแวดล้อมที่คล้ายโปรดักชัน”
    แต่ถ้าเป็นอีกกรณีใช้งานหนึ่งของ docker compose คือฝั่งพัฒนา ก็น่าจะมีทางเลือกที่ดีกว่านี้
    docker compose สามารถสตาร์ตฐานข้อมูล, Redis, OpenSearch, dependency อื่น ๆ, nginx proxy และคอนเทนเนอร์สำหรับพัฒนาที่เมานต์ .:/app เป็นโวลุ่มขึ้นมาพร้อมกันได้, ลบทั้งหมดพร้อมกันได้, และเก็บ docker-compose.yml ไว้ใน repository ได้
    แต่ Quadlet บอกให้วางไฟล์ทั้งหมดไว้ที่ ~/.config/containers/systemd จึงไม่ถูกแยกอยู่ในโปรเจ็กต์อีกต่อไป และไม่สะดวกนักที่จะ commit แล้วแชร์กับนักพัฒนาคนอื่น ๆ อีกทั้งพวกเขาก็ต้องใช้ Podman ด้วย
    คนส่วนใหญ่ยังคงใช้ Docker และแม้แต่ในสภาพแวดล้อมพัฒนาแบบโฮสต์อย่าง Codespaces ก็มี Docker ให้
    เลยใช้ docker compose กับไฟล์ YAML ที่ commit ไว้ ฉันใช้ Podman จึงต้องใส่ :Z ให้ทุกโวลุ่มด้วยมือตลอด แต่ Docker ทั่วไปจัดการสิ่งนั้นไม่ได้
    ถ้ามีทางเลือกแทน docker compose สำหรับงานพัฒนาก็คงดี แต่ Quadlet ดูไม่ค่อยเหมาะ

    • ถ้าใช้ podman-compose --in-pod=1 systemd -a create-unit ก็สามารถสร้างบริการ podman-compose@ ได้ และหลังจากนั้นใช้ podman-compose systemd -a register เพื่อลงทะเบียนไฟล์ compose.yml พร้อมกับ $name
      จากนั้นก็จัดการ pod ที่อิงจากไฟล์ compose ได้ด้วย podman-compose@$name.service และยังทำงานแบบ rootless ได้เต็มรูปแบบด้วย
    • ในกรณีนี้สิ่งที่ต้องการคือ Podman pod และฉันจะ orchestration ทั้งชุดด้วย Ansible แล้วแจกจ่าย Ansible playbook ให้ทุกคนเอาไปรันในเครื่องของตัวเอง
    • systemd-run ช่วยให้รัน บริการ systemd แบบชั่วคราว โดยอิงจากคำสั่งใดก็ได้
      ถ้าจำเป็น มันยังสร้าง unit ชั่วคราวที่เรียบร้อยและเป็นไปตามกฎของ systemd scope รวมถึง timer ให้ด้วย
      [1] https://www.freedesktop.org/software/systemd/man/systemd-run...
    • โดยรวมแล้วมองว่า Quadlet ใกล้เคียงกับการใช้งาน เพื่อ deploy มากกว่า ถ้ากำลังหาตัวแทน compose ก็ควรไปดู Podman Kube Play[1]
      มันใช้รูปแบบคล้าย Kubernetes และเพิ่มความสะดวกบางอย่างอย่างการ build container เข้ามาเล็กน้อย
      วางไฟล์ kube play ไว้ที่ root ของโปรเจ็กต์ แล้วรัน podman kube play project.yaml --build ก็จะสตาร์ตทั้ง pod, โวลุ่ม และอื่น ๆ ขึ้นมาด้วยกัน
      ส่วนไฟล์ Quadlet มีประโยชน์ในขั้น deploy ถ้าต้องการนำโปรเจ็กต์ขึ้น VPS ก็ใช้ Kube Quadlet[2] ร่วมกับ project.yaml ที่มีอยู่แล้วได้เลย
      [1] https://docs.podman.io/en/latest/markdown/podman-kube-play.1...
      [2] https://docs.podman.io/en/latest/markdown/podman-systemd.uni...
    • บริษัทเราก็ใช้ docker-compose.yml สำหรับงานพัฒนาเหมือนกัน เลยเข้าใจความลำบากนี้ดี
      โดยรวมมันทำงานได้ดีมาก แต่บน OSX บางครั้งก็มีอาการแปลก ๆ เพราะ VM ตัวกลางบ้านั่น
      เป็นครั้งคราวก็ลองเช็กความเข้ากันได้กับ Podman อยู่เหมือนกัน แต่ตอนนี้ยอมรับแล้วว่าคงทำให้เข้ากันได้แบบสมบูรณ์ไม่ได้ เพราะแนวคิดแบบ rootless ต่างกันมากเกินไป
      ถึงอย่างนั้น เครื่องมือนี้ก็ยอดเยี่ยมมากสำหรับโปรดักชัน ฉันมีโปรเจ็กต์งานอดิเรกอยู่ไม่กี่ตัวที่รันบน bare metal node ด้วยบริการ systemd ที่ทำขึ้นเอง ซึ่งตอนนี้ใช้ containerd โหมดผู้ใช้
      ถ้ามีเวลาก็อาจจะลองย้ายดู
  • น่าขำดีที่บทความนี้บอกว่า Podman-Compose “ไม่ได้มีการบำรุงรักษาอย่างต่อเนื่อง” โดยชี้ว่าคอมมิตล่าสุดคือเมื่อ 5 เดือนก่อน แล้วก็แนะนำ Podlet เป็นทางเลือกทันที ทั้งที่คอมมิตล่าสุดของมันก็เมื่อ 5 เดือนก่อนเหมือนกัน
    Podlet อาจมีประโยชน์ แต่ไม่รองรับฟีเจอร์จำนวนมากของ Docker Compose และก็ไม่ได้แปลงให้ออกมาสะอาดเรียบร้อยเสมอไป
    โดยเฉพาะอย่างยิ่งมันไม่รองรับการซ้อนหลายไฟล์ YAML แบบ -f docker-compose.yml -f docker-compose.override.yml

    • ถ้าคุณชอบไฟล์ compose ก็สามารถใช้ compose application ของ Docker[1] ร่วมกับ Podman[2] ได้
      ดูเหมือนว่า compose CLI จะควบคุมเอนจินผ่าน socket และ Podman กับ Docker engine ก็มี API ที่แทบจะเหมือนกัน
      ผมใช้วิธีนี้อยู่เพราะ podman-compose ทำงานไม่ได้ตามที่คาดหวัง
      โดยปกติ Docker-compose จะติดตั้งเป็นปลั๊กอินของไคลเอนต์ docker แต่ผมใช้แบบแอปพลิเคชันสแตนด์อโลนเพื่อใช้กับ Podman
      และสำหรับการตั้งค่าการเชื่อมต่อ ผมชอบใช้ docker contexts มากกว่าตัวแปรสภาพแวดล้อม DOCKER_HOST
      ถ้า Quadlet อย่างเดียวไม่ทรงพลังพอ ทั้ง Quadlet[3] และ Podman ปกติ[4] ก็รองรับการรัน Kubernetes manifest แบบจำกัดได้เช่นกัน
      ผมยังไม่ได้หาคำตอบว่า Podman จัดการตัวเลือก restart ในไฟล์ compose อย่างไร เพราะ Podman ไม่มี supervisor daemon
      แต่ผมรู้ว่าตัวเลือก healthcheck นั้นพึ่งพา systemd timer
      ตอนใช้ Podman บน Gentoo ซึ่งไม่ใช่ดิสโทรที่ใช้ systemd การตรวจสุขภาพอัตโนมัติใช้งานไม่ได้ แต่เมื่อรัน healthcheck แบบแมนนวลแล้ว การตั้งค่าที่เหลือก็ทำงานต่อจนจบ
      [1] https://github.com/docker/compose
      [2] https://docs.podman.io/en/latest/markdown/podman-system-serv...
      [3] https://docs.podman.io/en/latest/markdown/podman-systemd.uni...
      [4] https://docs.podman.io/en/latest/markdown/podman-kube-play.1...
    • ถ้ามองกันอย่างเป็นธรรม ฟังก์ชันของ Podlet ไม่ได้จำเป็นต้องอัปเดตต่อเนื่องตลอดเวลา แต่ podman compose ไม่เหมือนกัน
      Podlet เป็นเครื่องมือเสริม และในระยะยาวการทำงานกับ Quadlet โดยตรงน่าจะดีกว่า
    • วันที่ของคอมมิตอาจไม่ใช่ตัวชี้วัดที่แม่นยำว่าบางอย่างยังอยู่ระหว่างการบำรุงรักษา แต่ใช้บอกได้ว่ามันไม่ได้รับการบำรุงรักษา
      5 เดือนไม่ได้แปลว่าไม่มีการบำรุงรักษา ต้องระดับประมาณ 2 ปีถึงจะใช่
      ถึงอย่างนั้นมันก็ทำให้กังวลมากขึ้นได้ เพียงแต่ 5 เดือนไม่ใช่หลักฐานว่าโครงการยังได้รับการบำรุงรักษาแน่นอน
      แม้แต่รีโพซิทอรีที่ไม่ได้รับการบำรุงรักษาก็ยังมีเหตุผลมากมายที่อาจถูกอัปเดตได้ มีแค่ฟีเจอร์ archive ของ GitHub ที่ช่วงหลังแย่ลงเท่านั้นที่ช่วยกันเรื่องนี้ได้
  • เมื่อหลายปีก่อน ตอนรีเซ็ตระบบ self-hosting ผมอยากลองอย่างอื่นจึงเลือก openSUSE MicroOS และสุดท้ายก็ได้มารันคอนเทนเนอร์ Podman ภายใต้ systemd/Quadlet ซึ่งตอนนี้ผมพอใจกับชุดตั้งค่านี้มาก
    คอนเทนเนอร์อัปเดตอัตโนมัติด้วยเครื่องมือที่มีมาใน Podman และการดูล็อกกับมอนิเตอร์ก็ทำผ่านเครื่องมือ systemd ตามปกติ
    เวลาอยากเปลี่ยนอะไร ก็หาตำแหน่งไฟล์คอนฟิกได้ง่ายแม้จะลืมไปแล้ว และยังอ่านกับแก้ไขได้ง่ายด้วย
    แบบ rootless และ daemonless ก็ดีมาก
    ผมลองหลายอย่างระหว่างทาง แต่ podman compose ให้ความรู้สึกเทอะทะ รู้สึกดีที่มันถูก deprecated แล้ว และชัดเจนว่า Quadlet คือทิศทางที่ควรไป
    ต้องยอมรับว่ามี learning curve และมีข้อมูลน้อยกว่า Docker
    แต่ถ้าเป็นงาน local development ที่ต้องยกและปิดหลาย service stack อยู่เรื่อย ๆ ผมก็คงยังเลือก Docker และ docker compose

    • ผมรัน Nextcloud บน Fedora CoreOS บนเวิร์กสเตชันเก่าราคาถูก
      ใช้เวลาพอสมควรกว่าจะตั้งค่าลงตัว แต่ผมประทับใจมากที่มันแทบไม่ต้องบำรุงรักษาเลย จนถึงตอนนี้ยังไม่ต้องทำอะไรเลย
      ถ้าใครอยากลองทำแบบคล้ายกัน ก็อ้างอิงการตั้งค่าของผมได้
      https://github.com/jeppester/coreos-nextcloud
    • ชุด Quadlet + MicroOS ทรงพลังมาก และดิสโทรแบบ atomic อื่น ๆ อย่าง Fedora CoreOS ก็เช่นกัน
      ผมกำลังทยอยย้ายทุกโหนดไปเป็น MicroOS และที่บริษัทก็กำลังผลักดัน MicroOS หรือสิ่งที่คล้ายกันอยู่
      มันให้ความรู้สึกว่าการ rollback อัตโนมัติของ OS พื้นฐาน รวมกับการตั้งค่าคอนเทนเนอร์แบบ declarative และการอัปเดตอัตโนมัติ เข้ากันได้อย่างลงตัว
  • รูปแบบนี้ชัดเจนกว่า podman generate systemd หรือ Kubernetes YAML และ การผสานกับ systemd ก็ยอดเยี่ยม
    สิ่งที่น่าหงุดหงิดคือ Podman upstream ไม่ได้มีรีโพซิทอรีสำหรับ Debian/Ubuntu
    บน Debian stable มันถูกตรึงไว้ที่ 4.3.1 ทำให้พลาดฟีเจอร์ใหม่ไปมาก และสุดท้ายผมก็ตัดสินใจกลับไปใช้ Docker compose

    • ผมเจอปัญหาเดียวกันตอนพยายามใช้ Quadlet บน Raspberry Pi ที่รัน Debian
      วิธีแก้ชั่วคราวที่มีคนเสนอคือคอมไพล์ Podman เองหรือใช้ debian/testing
  • หวังอย่างจริงใจว่าแนวทางใหม่นี้จะช่วยให้ผู้คนย้ายจาก Docker ไปใช้ Podman ได้
    Docker-Compose เป็นเหตุผลที่ทำให้หลายคนลังเลที่จะย้าย และผมก็เป็นแบบนั้นเหมือนกัน
    พูดกันตามตรง ก่อนมี Quadlet นั้น Podman ไม่มีคำตอบที่ดีพอจริง ๆ
    ถ้าคุณลังเลที่จะย้ายออกจาก Docker เพราะ Docker-Compose, Podman ที่ใช้คู่กับ Quadlet ก็เป็นทางเลือกที่สมน้ำสมเนื้อกว่ามาก
    คุณอาจไม่ได้คิดถึง Docker อย่างที่คิดไว้ และยังได้ความปลอดภัยที่ดีขึ้นจากการรันคอนเทนเนอร์แบบ rootless ด้วย

    • ฉันจะยังไม่ย้ายจนกว่าจะมี สภาพแวดล้อม Quadlet แบบแยกอิสระหลายชุดได้
      วิธีที่ให้ใส่ทุกอย่างไว้ใน ~/.config/quadlet/systemd ใช้ไม่ได้
      เรื่องนี้จำเป็นมากสำหรับงานพัฒนาและการทดสอบ และตอนนี้ Quadlet ยังเป็นโซลูชันสำหรับการดีพลอยอย่างเคร่งครัด
  • ผมชอบ Quadlet มากเพราะมันทำให้ใช้คอนเทนเนอร์ได้เหมือนบริการระบบทั่วไป
    แต่ประสบการณ์ใช้งานของ คอนเทนเนอร์แบบ rootless กลับไม่ค่อยเข้ากับแนวคิดนี้นัก
    โดยปกติบริการระบบจะรันใน systemd session ของระบบในฐานะ system user แต่บริการของคอนเทนเนอร์แบบ rootless จะอยู่ใน user systemd session ของ system user นั้น
    น่าจะดีถ้าสามารถรัน rootless Quadlet ภายใน system session ได้

    • สงสัยว่ามันมีความต่างในทางปฏิบัติหรือไม่ ระหว่างการเปิด user-linger แล้วรันแบบ rootless ผ่าน user systemd
      ผมทำแบบนั้นมาตลอด
    • ผมก็อยากให้สามารถรัน system session ภายใน rootless Quadlet ได้เช่นกัน
      และอยากให้สามารถรัน rootless Quadlet ด้วยตัวเลือก DynamicUser= ได้ด้วย
      DynamicUser= เป็นวิธีที่ยอดเยี่ยมในการจำกัดสิทธิ์ของ system service แต่ตอนนี้มันยังเข้ากับ Podman ได้ไม่ดี
  • น่าสนใจที่ได้เห็น Quadlet บนหน้าแรกของ Hacker News คิดว่ามันยังไม่ได้รับความสนใจมากพอ
    Ygal และ Valentin จากโปรเจกต์นี้เคยส่งบทความรับเชิญเกี่ยวกับวิธีรันไคลเอนต์ inlets tunnel มาให้ เป็นอะไรคล้าย Ngrok/Cloudflared แต่โฮสต์เองได้โดยไม่มีข้อจำกัดแบบ SaaS
    https://inlets.dev/blog/2023/10/03/client-quadlet.html
    พวกเขาใช้ [kube] แทน [container] จึงสามารถนำ Kubernetes YAML มาตรฐานมาใช้ได้ และทำให้พกพาได้ดีพอสมควร

  • สำหรับคนที่สนใจ ผมได้ทำ Ansible template ไว้เพื่อแสดงให้เห็นว่าช่วงนี้การดีพลอย Quadlet นั้นง่ายแค่ไหน
    GH: https://github.com/Mati365/hetzner-podman-bunjs-deploy