10 คะแนน โดย GN⁺ 2024-01-09 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Dive เป็นเครื่องมือสำหรับสำรวจเลเยอร์และเนื้อหาไฟล์ของอิมเมจ Docker/OCI และค้นหาโอกาสในการลดขนาดอิมเมจ
  • สามารถรัน dive <your-image-tag> ด้วยแท็กอิมเมจ, ID หรือไดเจสต์ หรือใช้ dive build -t <some-tag>. เพื่อทำ การวิเคราะห์ทันทีหลัง build ได้ในคำสั่งเดียว
  • เมื่อเลือกเลเยอร์ จะแสดง file tree ที่รวมเลเยอร์นั้นกับเลเยอร์ก่อนหน้าไว้ด้วยกัน และสามารถตรวจสอบไฟล์ที่เพิ่ม แก้ไข ลบ รวมถึงการเปลี่ยนแปลงสะสมได้จาก file tree
  • ตัวชี้วัดเชิงทดลอง image efficiency จะประเมินพื้นที่ที่สูญเปล่าจากไฟล์ซ้ำ การย้ายไฟล์ข้ามเลเยอร์ และไฟล์ที่ไม่ได้ถูกลบออกอย่างสมบูรณ์ เป็นคะแนนและขนาดรวม
  • สามารถตั้ง CI=true เพื่อข้าม UI และคืนผลผ่าน/ไม่ผ่านตามเกณฑ์ประสิทธิภาพของอิมเมจและพื้นที่สูญเปล่า ช่วยทำให้การจัดการขนาดอิมเมจใน CI pipeline เป็นอัตโนมัติได้

Dive ทำอะไรได้บ้าง

  • Dive เป็นเครื่องมือสำหรับสำรวจอิมเมจ Docker, เนื้อหาเลเยอร์ และวิธีลดขนาดอิมเมจ Docker/OCI
  • การรันพื้นฐานคือส่งแท็กอิมเมจ, ID หรือไดเจสต์เข้าไป
    • dive <your-image-tag>
  • สามารถรันผ่าน Docker container ได้เช่นกัน โดยต้อง mount Docker socket
    • ใช้อิมเมจ docker.io/wagoodman/dive
    • มีการยก nginx:latest เป็นตัวอย่างอิมเมจเป้าหมาย
  • หากต้องการวิเคราะห์ทันทีหลัง build อิมเมจ สามารถใช้คำสั่ง dive build ในรูปแบบเดียวกันแทน docker build ได้
    • dive build -t <some-tag> .
  • วิธีรันการวิเคราะห์ build ผ่าน container บน macOS รองรับเฉพาะ Docker container engine เท่านั้น
  • สถานะของโปรเจกต์เป็น beta quality และสามารถส่งคำขอฟีเจอร์ใหม่หรือบั๊กผ่าน issue ได้

สำรวจเลเยอร์และการเปลี่ยนแปลงไฟล์

  • เมื่อเลือกเลเยอร์ทางซ้าย ทางขวาจะแสดง file tree ที่รวมเลเยอร์นั้นกับเลเยอร์ก่อนหน้าไว้ด้วยกัน
  • สามารถใช้ปุ่มลูกศรเพื่อสำรวจ file tree ได้
  • สถานะของไฟล์ที่เปลี่ยนแปลงในแต่ละเลเยอร์จะแสดงอยู่ใน file tree
    • เปลี่ยนแปลงแล้ว
    • แก้ไขแล้ว
    • เพิ่มแล้ว
    • ลบแล้ว
  • รูปแบบการแสดงการเปลี่ยนแปลงสามารถปรับได้ว่าจะอิงตามเลเยอร์เฉพาะ หรืออิงตาม การเปลี่ยนแปลงสะสม จนถึงเลเยอร์นั้น

ประเมินประสิทธิภาพอิมเมจและพื้นที่สูญเปล่า

  • แผงด้านซ้ายล่างจะแสดงข้อมูลเลเยอร์พื้นฐานและตัวชี้วัดเชิงทดลอง image efficiency
  • ตัวชี้วัดนี้ประเมินพื้นที่สูญเปล่าภายในอิมเมจ
    • ไฟล์ซ้ำระหว่างเลเยอร์
    • การย้ายไฟล์ระหว่างเลเยอร์
    • ไฟล์ที่ไม่ได้ถูกลบออกอย่างสมบูรณ์
  • ผลลัพธ์จะแสดงเป็น score แบบเปอร์เซ็นต์และพื้นที่ไฟล์สูญเปล่าทั้งหมด

ใช้เป็นเกณฑ์ผ่าน/ไม่ผ่านใน CI

  • เมื่อรันด้วย environment variable CI=true Dive จะข้าม UI วิเคราะห์อิมเมจ แล้วให้ผลลัพธ์ pass/fail ผ่าน return code
  • สามารถตั้งค่าเกณฑ์ 3 แบบได้ด้วยไฟล์ .dive-ci ที่ root ของ repository
    • lowestEfficiency: ล้มเหลวหากประสิทธิภาพต่ำกว่าอัตราที่กำหนด
    • highestWastedBytes: ล้มเหลวหากพื้นที่สูญเปล่ามากกว่าหรือเท่ากับขนาดที่กำหนด
    • highestUserWastedPercent: ล้มเหลวหากสัดส่วนพื้นที่สูญเปล่าตาม user layer มากกว่าหรือเท่ากับอัตราที่กำหนด
  • ในการคำนวณ highestUserWastedPercent จะไม่นับ base image layer รวมในขนาดอิมเมจทั้งหมด
  • สามารถ override path ของไฟล์ตั้งค่า CI ได้ด้วยตัวเลือก --ci-config

แหล่งอิมเมจและ container engine

  • สามารถเลือกตำแหน่งที่จะดึง container image ได้ด้วยตัวเลือก --source
    • dive <your-image> --source <source>
    • dive <source>://<your-image>
  • ตัวเลือก source ที่รองรับมีดังนี้
    • docker: Docker engine, ค่าเริ่มต้น
    • docker-archive: Docker Tar Archive บนดิสก์
    • podman: Podman engine, รองรับเฉพาะ Linux

การติดตั้งและวิธีรัน

  • Ubuntu/Debian สามารถติดตั้งด้วยแพ็กเกจ .deb หรือ Snap ได้
  • วิธี Snap ไม่แนะนำหากติดตั้ง Docker ด้วย apt-get และมีคำเตือนว่าอาจทำให้ Docker daemon เดิมเสียหายได้
  • RHEL/Centos สามารถติดตั้งด้วยแพ็กเกจ .rpm ได้
  • Arch Linux มีให้ใน extra repository และติดตั้งได้ด้วย pacman
  • macOS สามารถติดตั้งด้วย Homebrew, MacPorts หรือ build สำหรับ Darwin จาก releases page
  • Windows สามารถติดตั้งด้วย Chocolatey, scoop, winget หรือ build สำหรับ Windows จาก releases page
  • หากต้องการติดตั้งด้วยเครื่องมือ Go ต้องใช้ Go 1.10 ขึ้นไป
    • go install github.com/wagoodman/dive@latest
    • เมื่อติดตั้งด้วยวิธีนี้ การรัน dive -v จะไม่แสดงเวอร์ชันที่ถูกต้อง
  • มีวิธีติดตั้งผ่าน Nix/NixOS และ x-cmd ให้ด้วย
  • เมื่อรันด้วย Docker image ต้องรวมไฟล์ Docker socket เข้าไปด้วย
    • -v /var/run/docker.sock:/var/run/docker.sock
  • ขึ้นอยู่กับเวอร์ชัน Docker ในเครื่อง อาจต้องใช้ environment variable เช่น DOCKER_API_VERSION=1.37
  • หากใช้ runtime ทางเลือกอย่าง Colima อาจต้องกำหนด environment variable DOCKER_HOST เพื่อดึงอิมเมจในเครื่อง

การใช้งานและตั้งค่า UI

  • key binding หลักใช้สำหรับสลับไปมาระหว่างมุมมองเลเยอร์กับมุมมอง file tree เพื่อสำรวจ กรอง และ toggle การแสดงผล
    • Ctrl+C หรือ Q: ออก
    • Tab: สลับระหว่างมุมมองเลเยอร์และมุมมอง file tree
    • Ctrl+F: ตัวกรองไฟล์
    • Ctrl+A: ในมุมมองเลเยอร์ แสดงการเปลี่ยนแปลงอิมเมจแบบสะสม; ในมุมมอง file tree toggle การแสดงไฟล์ที่เพิ่ม
    • Ctrl+L: แสดงการเปลี่ยนแปลงของเลเยอร์ปัจจุบัน
    • Ctrl+R, Ctrl+M, Ctrl+U: toggle การแสดงไฟล์ที่ลบ แก้ไข และไม่มีการเปลี่ยนแปลง
    • Ctrl+B: toggle การแสดงคุณสมบัติไฟล์
  • ไม่จำเป็นต้องตั้งค่าแยกต่างหาก แต่สามารถ override ค่าได้ด้วยไฟล์ตั้งค่า YAML
  • รายการที่ตั้งค่าได้รวมถึง container engine, การเพิกเฉยต่อข้อผิดพลาดในการ parse image archive, log, key binding, การแสดง diff, ความกว้างของ file tree, สถานะพับของไดเรกทอรีโดยค่าเริ่มต้น และการแสดงการเปลี่ยนแปลงสะสมของเลเยอร์
  • ตำแหน่งที่ค้นหาไฟล์ตั้งค่ามีดังนี้
    • $XDG_CONFIG_HOME/dive/*.yaml
    • $XDG_CONFIG_DIRS/dive/*.yaml
    • ~/.config/dive/*.yaml
    • ~/.dive.yaml
  • สามารถใช้นามสกุล .yml แทน .yaml ได้

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

 
GN⁺ 2024-01-09
ความคิดเห็นจาก Hacker News
  • เมื่อต้องจัดการอิมเมจกับเลเยอร์ crane เป็นเครื่องมือที่ยอดเยี่ยม และไลบรารีพื้นฐานอย่าง go-containerregistry ก็ดีเช่นกัน
    สามารถเพิ่มเลเยอร์ใหม่ให้กับอิมเมจเดิม หรือแก้ไขเมทาดาทา (env vars, labels, entrypoint ฯลฯ) ได้ และยังสามารถ “ทำให้แบน” โดยรวมอิมเมจหลายเลเยอร์ให้เป็นเลเยอร์เดียวได้ด้วย
    นอกจากนี้ยังทำ “rebase” ที่นำการเปลี่ยนแปลงไปใช้ซ้ำกับเบสอิมเมจใหม่ได้ และทั้งหมดนี้ทำได้โดยตรงบน registry จึงไม่ต้องใช้ Docker
    https://github.com/google/go-containerregistry/blob/main/cmd...

    • เป็นคำแนะนำที่ดี ต่างจาก Docker ตรงที่ crane ทำงานได้ โดยไม่ต้องใช้ root และ daemon จึงเหมาะกับการใช้บน Nix และใน Nix repository ก็มีให้ในชื่อ crane
      ด้วยเหตุนี้จึงใช้ Nix จัดการได้ทั้ง dependency สำหรับ build (เช่น Go) และเครื่องมือสำหรับแพ็กเกจ/ดีพลอย (เช่น gnu tar, crane) ไปพร้อมกัน
    • สงสัยว่าถ้าจำนวนเลเยอร์น้อยจะได้ประโยชน์ด้านประสิทธิภาพหรือไม่ เข้าใจว่าแม้รวมอิมเมจแล้วขนาดรวมยังเท่าเดิม ดังนั้น การรวมเลเยอร์ เองไม่น่าจะให้ประโยชน์อะไร
  • dive มีประโยชน์มากจริง ๆ ในการทำความเข้าใจว่า Docker image ทำงานอย่างไร และจะเขียน Dockerfile ให้มีประสิทธิภาพได้อย่างไร
    การอ่านเอกสารก็สำคัญ แต่การได้เห็นเองว่าโครงสร้างเลเยอร์ของผลลัพธ์เปลี่ยนไปอย่างไรหลังแก้ Dockerfile เป็นสิ่งชี้ขาดต่อความเข้าใจ

  • Dive ยอดเยี่ยมมาก เครื่องมือแบบนี้สำคัญต่อการเรียนรู้และสร้างความมั่นใจว่าฉันกำลัง build และ deploy อะไรกันแน่
    Dredge ก็เป็นเครื่องมือที่น่าดู และใช้ตอนเปรียบเทียบความต่างของเลเยอร์
    https://github.com/mthalman/dredge/blob/main/docs/commands/i...

    • ดูดีมากจริง ๆ ตอนที่อาศัยความช่วยเหลือจาก HN และ Reddit เพื่อตามรอยว่า Raspberry Pi น่าสงสัย ในห้องเซิร์ฟเวอร์กำลังทำอะไรอยู่ คงต้องการเครื่องมือแบบนี้พอดี
      https://blog.haschek.at/2019/the-curious-case-of-the-RasPi-i...
  • อาจเป็นคำถามโง่ ๆ แต่สงสัยว่าทำไมเครื่องมือด้านคอนเทนเนอร์/โครงสร้างพื้นฐานส่วนใหญ่จึงเขียนด้วย Go
    นึกถึง Docker, Podman, nerdctl, Terraform, Kubernetes เลยอยากรู้ว่า Go มีข้อได้เปรียบที่ชัดเจนอะไรในการสร้างเครื่องมือประเภทนี้หรือไม่

    • ตอบในส่วนของ Docker ได้ โปรโตไทป์แรกเขียนด้วย Python และบริษัทก็เน้น Python เป็นหลัก
      เหตุผลหลักที่เขียนใหม่ด้วย Go คือเพื่อเกาะกระแส ความนิยมของ Go ที่กำลังเติบโตในตอนนั้น (ปี 2012) ผมอยู่ตรงนั้นด้วย
    • Go เป็นภาษาที่ cross-compile และ deploy ง่ายที่สุด มีประสิทธิภาพดีเมื่อเทียบกับ productivity มี concurrency ในตัวที่ดี และความสามารถด้าน networking ใน standard library ก็ยอดเยี่ยม
      ลองจินตนาการว่า Docker และ Kubernetes เขียนด้วยภาษายอดนิยมอื่น ๆ จะเห็นความต่างชัดเจน
    • มองว่าเครื่องมือระบบ, utility, command-line tool และซอฟต์แวร์ networking คือพื้นที่ที่ Go เปล่งประกายที่สุด
      ทางเลือกสมัยใหม่ที่โตพอแล้วดูเหมือนจะมีแค่ Rust เท่านั้น
    • เหตุที่ Kubernetes เขียนด้วย Go ก็เพราะ Google สร้าง Go และสร้าง Kubernetes ด้วย
      การที่ทีมภายในมีวิศวกร Go จำนวนมากก็ด้วยเหตุผลเดียวกัน
    • ตอนรันคอนเทนเนอร์ เราอยากไม่ต้องสนใจระบบพื้นฐานให้มากที่สุด และ Go ทำให้โปรแกรมทำงานอยู่ในโลกเล็ก ๆ ของตัวเองได้ง่าย
      แถมยังมีผลจาก ecosystem ด้วย จึงนำแพ็กเกจจาก implementation อื่นมาใช้ในบางส่วนของโค้ดได้ทันที
  • ชอบ Dive และหยิบออกมาใช้จากกล่องเครื่องมือหลายครั้งต่อเดือน
    แต่สงสัยว่ามีวิธีดูเนื้อหาของไฟล์ที่เลือกได้ทันทีหรือไม่ หลายครั้งต้องการตรวจว่าไฟล์มีอยู่ในเลเยอร์ไหมแล้วดูเนื้อหา ตอนนี้มักจะรันคอนเทนเนอร์แล้วใช้ cat หรือแตกเนื้อหาออกมาแล้วไล่เข้าโฟลเดอร์

    • ใช้ rsync ร่วมกับทริกเล็กน้อยเพื่อเข้าถึงไฟล์ได้ แต่ก็ไม่ได้ต่างจากการใช้ cat มากนัก
  • ตอนขยาย Docker container สาธารณะหลายตัว Dive ช่วยชีวิตไว้หลายครั้งระหว่างแกะดูว่าข้างในทำอะไรอยู่
    เป็นซอฟต์แวร์ระดับ A+ จริง ๆ

  • ยังมี เครื่องมือ TUI บนเทอร์มินัล ดี ๆ แบบ dive อีกหลายตัว นึกถึง lazydocker และ dry
    ในหมวด Docker ก็มีอยู่หลายตัว
    [0] https://terminaltrove.com/

    • Lazydocker ก็มีฟีเจอร์คล้ายกันแต่เรียบง่ายกว่า
      ลองดูแล้ว เห็นเลเยอร์ได้ แต่แสดงเฉพาะคำสั่งของแต่ละเลเยอร์
  • Dive เป็นเครื่องมือที่น่าทึ่งในโลกคอนเทนเนอร์/Docker ทำให้การดีบักว่าจริง ๆ แล้วมีอะไรอยู่ในคอนเทนเนอร์ง่ายขึ้นมาก
    ตอนเริ่ม Depot [0] ใหม่ ๆ มักถูกถามบ่อยว่าจะลดขนาดอิมเมจและทำให้ build เร็วขึ้นได้อย่างไร เลยเขียนบทความสั้น ๆ [1] อธิบายวิธีแก้ปัญหานั้นด้วย Dive ไว้ ตอนนี้อาจจะเก่าไปบ้างแล้ว แต่ก็อาจเป็นประโยชน์กับใครบางคน
    ได้แรงบันดาลใจจาก Dive เราจึงทำให้มองเห็นได้ง่ายขึ้นด้วยว่าใน build context มีอะไรอยู่จริง ๆ ในทุก build และปล่อยเป็นฟีเจอร์ของ Depot เมื่อไม่กี่สัปดาห์ก่อน
    [0] https://depot.dev
    [1] https://depot.dev/blog/reducing-image-size-with-dive
    [2] https://depot.dev/blog/build-context

  • นอกจาก Dive จะมีประโยชน์มากแล้ว ยังมีข้อดีที่ถูกประเมินต่ำไปอีกอย่างคือ ผู้เขียนเป็น นักพัฒนาที่ยอดเยี่ยม และเป็นคนที่ร่วมงานด้วยแล้วสนุกจริง ๆ

  • เครื่องมือของ Google ที่ชื่อ container-diff ก็มีประโยชน์มากจริง ๆ
    ใช้เวลาต้องการดูว่าสคริปต์สุ่ม ๆ ที่แนะนำให้ pipe เข้า bash แล้วรัน จะทำอะไรกับระบบบ้าง

    • แม้จะเกี่ยวข้องกับ utility ทั่วไปของคอนเทนเนอร์น้อยกว่านิดหน่อย แต่ผมใช้ GoogleContainerTools/container-structure-test อย่างจริงจัง
      เป็นวิธีที่สะดวกในการรัน integration test กับแอปหรืออิมเมจคอนเทนเนอร์
      น่าเสียดายที่โปรเจกต์โอเพนซอร์สของ Google แบบนี้ดูเหมือนคนที่เคยดูแลเดิมออกไปกันมาก จึงต้องการคนช่วยดูแล พอมีโอกาสก็พยายามส่ง PR และปิด issue เป็นครั้งคราว โดยเฉพาะเครื่องมือทดสอบตัวนี้มีค่ามากในการรักษาสติเมื่อต้องจัดการเบสอิมเมจจำนวนมากที่ต้องดูแลภายใน