10 điểm bởi GN⁺ 2024-01-09 | 1 bình luận | Chia sẻ qua WhatsApp
  • Dive là công cụ để khám phá các layer và nội dung file của Docker/OCI image, đồng thời tìm cơ hội giảm kích thước image
  • Có thể chạy dive <your-image-tag> bằng tag, ID hoặc digest của image; hoặc dùng dive build -t <some-tag>. để thực hiện phân tích ngay sau khi build trong cùng một bước
  • Khi chọn một layer, công cụ hiển thị cây file được hợp nhất từ layer đó và các layer trước đó; có thể xem các file được thêm, sửa, xóa và các thay đổi tích lũy trong cây file
  • Chỉ số image efficiency mang tính thử nghiệm ước tính không gian lãng phí phát sinh từ file trùng lặp, file di chuyển giữa các layer và file không bị xóa hoàn toàn, dưới dạng điểm số và tổng dung lượng
  • Với CI=true, có thể bỏ qua UI và trả về kết quả đạt/không đạt dựa trên tiêu chí hiệu quả image và không gian lãng phí, giúp tự động hóa việc quản lý kích thước image trong CI pipeline

Dive làm gì

  • Dive là công cụ để khám phá Docker image, nội dung layer và các cách giảm kích thước Docker/OCI image
  • Cách chạy cơ bản là truyền vào tag, ID hoặc digest của image
    • dive <your-image-tag>
  • Cũng có thể chạy bằng Docker container; khi đó cần mount Docker socket
    • Sử dụng image docker.io/wagoodman/dive
    • nginx:latest được đưa ra làm image ví dụ mục tiêu
  • Để phân tích ngay sau khi build image, có thể dùng lệnh dive build với cùng dạng thay cho docker build
    • dive build -t <some-tag> .
  • Cách chạy phân tích build bằng container trên macOS chỉ hỗ trợ Docker container engine
  • Trạng thái dự án là beta quality; có thể gửi yêu cầu tính năng mới hoặc bug qua issue

Khám phá layer và thay đổi file

  • Khi chọn một layer ở bên trái, cây file hợp nhất layer đó với các layer trước đó sẽ được hiển thị ở bên phải
  • Có thể dùng các phím mũi tên để duyệt cây file
  • Trạng thái các file thay đổi trong từng layer được hiển thị trong cây file
    • Đã thay đổi
    • Đã sửa
    • Đã thêm
    • Đã xóa
  • Cách hiển thị thay đổi có thể được điều chỉnh theo một layer cụ thể hoặc theo thay đổi tích lũy đến layer đó

Ước tính hiệu quả image và không gian lãng phí

  • Panel phía dưới bên trái hiển thị thông tin layer cơ bản và chỉ số image efficiency mang tính thử nghiệm
  • Chỉ số này ước tính không gian lãng phí trong image
    • File trùng lặp giữa các layer
    • File di chuyển giữa các layer
    • File không bị xóa hoàn toàn
  • Kết quả được cung cấp dưới dạng score phần trăm và tổng dung lượng file lãng phí

Dùng làm tiêu chí đạt/không đạt trong CI

  • Khi chạy với biến môi trường CI=true, Dive sẽ bỏ qua UI, phân tích image rồi cung cấp kết quả pass/fail qua mã trả về
  • Có thể thiết lập 3 tiêu chí bằng file .dive-ci ở root của repository
    • lowestEfficiency: thất bại nếu hiệu quả thấp hơn tỷ lệ được chỉ định
    • highestWastedBytes: thất bại nếu không gian lãng phí bằng hoặc vượt dung lượng được chỉ định
    • highestUserWastedPercent: thất bại nếu tỷ lệ lãng phí theo layer người dùng bằng hoặc vượt tỷ lệ được chỉ định
  • Trong cách tính highestUserWastedPercent, base image layer không được tính vào tổng kích thước image
  • Có thể ghi đè đường dẫn file cấu hình CI bằng tùy chọn --ci-config

Nguồn image và container engine

  • Có thể chọn nơi lấy container image bằng tùy chọn --source
    • dive <your-image> --source <source>
    • dive <source>://<your-image>
  • Các tùy chọn source được hỗ trợ như sau
    • docker: Docker engine, giá trị mặc định
    • docker-archive: Docker Tar Archive trên đĩa
    • podman: Podman engine, chỉ hỗ trợ Linux

Cài đặt và cách chạy

  • Ubuntu/Debian có thể cài bằng gói .deb hoặc Snap
  • Cách dùng Snap không được khuyến nghị nếu Docker được cài bằng apt-get, và có cảnh báo rằng nó có thể làm hỏng Docker daemon hiện có
  • RHEL/Centos có thể cài bằng gói .rpm
  • Arch Linux được cung cấp trong extra repository và có thể cài bằng pacman
  • macOS có thể cài bằng Homebrew, MacPorts, hoặc bản build Darwin trên releases page
  • Windows có thể cài bằng Chocolatey, scoop, winget, hoặc bản build Windows trên releases page
  • Để cài bằng công cụ Go, cần Go 1.10 trở lên
    • go install github.com/wagoodman/dive@latest
    • Nếu cài theo cách này, phiên bản đúng sẽ không hiển thị khi chạy dive -v
  • Cũng có các cách cài đặt bằng Nix/NixOS và x-cmd
  • Khi chạy bằng Docker image, cần bao gồm file Docker socket
    • -v /var/run/docker.sock:/var/run/docker.sock
  • Tùy phiên bản Docker cục bộ, có thể cần biến môi trường như DOCKER_API_VERSION=1.37
  • Nếu dùng runtime thay thế như Colima, có thể cần chỉ định biến môi trường DOCKER_HOST để lấy image cục bộ

Điều khiển và cấu hình UI

  • Các phím tắt chính dùng để di chuyển giữa chế độ xem layer và cây file, cũng như duyệt, lọc và bật/tắt hiển thị
    • Ctrl+C hoặc Q: thoát
    • Tab: chuyển đổi giữa chế độ xem layer và chế độ xem cây file
    • Ctrl+F: lọc file
    • Ctrl+A: trong chế độ xem layer là xem thay đổi image tích lũy, trong chế độ xem cây file là bật/tắt hiển thị file đã thêm
    • Ctrl+L: xem thay đổi của layer hiện tại
    • Ctrl+R, Ctrl+M, Ctrl+U: bật/tắt hiển thị file đã xóa, đã sửa, không thay đổi
    • Ctrl+B: bật/tắt hiển thị thuộc tính file
  • Không cần cấu hình riêng, nhưng có thể ghi đè giá trị bằng file cấu hình YAML
  • Các mục có thể cấu hình gồm container engine, có bỏ qua lỗi phân tích image archive hay không, log, phím tắt, hiển thị diff, chiều rộng cây file, trạng thái thu gọn mặc định của thư mục và hiển thị thay đổi tích lũy của layer
  • Các vị trí tìm file cấu hình như sau
    • $XDG_CONFIG_HOME/dive/*.yaml
    • $XDG_CONFIG_DIRS/dive/*.yaml
    • ~/.config/dive/*.yaml
    • ~/.dive.yaml
  • Cũng có thể dùng phần mở rộng .yml thay cho .yaml

1 bình luận

 
GN⁺ 2024-01-09
Các ý kiến trên Hacker News
  • Khi làm việc với image và layer, crane rất tuyệt, và thư viện nền tảng go-containerregistry cũng tốt
    Nó có thể thêm layer mới vào image hiện có, chỉnh sửa metadata (env vars, labels, entrypoint, v.v.), và cũng có thể “làm phẳng” image nhiều layer thành một layer duy nhất
    Ngoài ra còn có thể “rebase”, tức áp dụng lại các thay đổi lên một base image mới; tất cả thao tác này được xử lý trực tiếp trên registry nên không cần Docker
    https://github.com/google/go-containerregistry/blob/main/cmd...

    • Gợi ý hay. Khác với Docker, crane hoạt động không cần root và daemon, nên rất tiện dùng với Nix, và cũng có sẵn trong kho Nix dưới tên crane
      Nhờ vậy có thể dùng Nix để quản lý cùng lúc không chỉ các dependency phục vụ build (ví dụ Go), mà cả công cụ đóng gói/phân phối (ví dụ gnu tar, crane)
    • Mình tò mò liệu ít layer hơn có lợi về hiệu năng không. Vì dù gộp image thì tổng dung lượng vẫn giữ nguyên, nên mình hiểu là bản thân việc gộp layer không đem lại lợi ích gì
  • dive thật sự hữu ích để hiểu Docker image hoạt động như thế nào và cách viết Dockerfile hiệu quả
    Đọc tài liệu cũng quan trọng, nhưng việc trực tiếp xem cấu trúc layer kết quả thay đổi ra sao sau khi sửa Dockerfile mới là yếu tố quyết định để hiểu vấn đề

  • Dive rất tuyệt. Những công cụ như thế này rất quan trọng để mình học và tự tin rằng mình đang build và deploy chính xác thứ gì
    Dredge cũng là một công cụ đáng xem, mình dùng nó khi so sánh khác biệt giữa các layer
    https://github.com/mthalman/dredge/blob/main/docs/commands/i...

  • Có thể là câu hỏi ngớ ngẩn, nhưng mình tò mò vì sao phần lớn công cụ container/hạ tầng lại được viết bằng Go
    Mình nghĩ đến Docker, Podman, nerdctl, Terraform, Kubernetes, và muốn biết liệu Go có lợi thế rõ rệt nào khi làm những công cụ như vậy không

    • Về Docker thì mình có thể trả lời. Prototype đầu tiên được viết bằng Python, và công ty lúc đó cũng xoay quanh Python
      Lý do chính để viết lại bằng Go là nhằm bắt theo độ phổ biến của Go khi đó (năm 2012) đang tăng lên. Mình đã ở đó
    • Go là ngôn ngữ dễ nhất cho cross-compile và phân phối, có hiệu năng tốt so với năng suất, concurrency tích hợp sẵn tốt, và khả năng networking trong thư viện chuẩn cũng tuyệt vời
      Thử tưởng tượng Docker và Kubernetes được viết bằng một ngôn ngữ phổ biến khác sẽ thấy khác biệt
    • Mình nghĩ công cụ hệ thống, tiện ích, công cụ dòng lệnh và phần mềm networking là những lĩnh vực Go tỏa sáng nhất
      Trong các lựa chọn hiện đại và trưởng thành, có vẻ chỉ có Rust là phương án thay thế
    • Kubernetes được viết bằng Go vì Google tạo ra Go và cũng tạo ra Kubernetes
      Việc các đội nội bộ có nhiều kỹ sư Go cũng cùng một lý do
    • Khi chạy container, bạn muốn càng ít phải bận tâm đến hệ thống nền càng tốt, và Go giúp chương trình dễ vận hành trong thế giới nhỏ riêng của nó
      Hơn nữa còn có hiệu ứng hệ sinh thái, nên có thể tận dụng ngay các package từ những implementation khác vào một phần code của mình
  • Mình thích Dive và mỗi tháng lôi nó ra khỏi hộp công cụ vài lần
    Tuy vậy mình thắc mắc có cách nào xem trực tiếp nội dung file đã chọn không. Nhiều khi sau khi xác nhận một file tồn tại trong layer, mình muốn xem nội dung của nó; hiện giờ thường phải chạy container rồi dùng cat, hoặc trích xuất nội dung rồi lần vào thư mục

    • Có thể dùng rsync để truy cập file với một chút mẹo, nhưng cũng không khác cat là mấy
  • Khi mở rộng nhiều Docker container công khai, Dive đã cứu mình vài lần trong quá trình mổ xẻ xem bên trong chúng làm gì
    Thật sự là phần mềm hạng A+

  • Còn nhiều công cụ TUI trên terminal tuyệt vời giống dive. Mình nghĩ đến lazydocker và dry
    Trong nhóm Docker cũng có vài công cụ
    [0] https://terminaltrove.com/

    • Lazydocker cũng có chức năng tương tự nhưng đơn giản hơn
      Mình kiểm tra thì nó có thể xem layer, nhưng chỉ hiển thị lệnh của từng layer
  • Dive là một công cụ đáng kinh ngạc trong mảng container/Docker. Việc debug xem thực sự có gì bên trong container trở nên dễ hơn nhiều
    Khi mới bắt đầu Depot [0], chúng tôi thường được hỏi cách giảm kích thước image và tăng tốc build, nên đã viết một bài ngắn [1] về cách giải quyết vấn đề đó bằng Dive. Giờ có thể hơi cũ, nhưng vẫn có thể hữu ích với ai đó
    Lấy cảm hứng từ Dive, chúng tôi cũng làm cho việc thấy rõ thực sự có gì trong build context ở mỗi lần build trở nên dễ hơn, và đã ra mắt tính năng này trong Depot vài tuần trước
    [0] https://depot.dev
    [1] https://depot.dev/blog/reducing-image-size-with-dive
    [2] https://depot.dev/blog/build-context

  • Ngoài việc rất hữu ích, Dive còn có một điểm mạnh bị đánh giá thấp: tác giả là một lập trình viên tuyệt vời và là người làm việc cùng thật sự dễ chịu

  • Công cụ container-diff của Google cũng thật sự hữu ích
    Mình dùng nó để kiểm tra một script tùy ý được khuyến nghị pipe qua bash để chạy sẽ làm gì với hệ thống

    • Dù hơi ít liên quan hơn đến các tiện ích container nói chung, mình đang dùng GoogleContainerTools/container-structure-test rất tích cực
      Đây là cách thuận tiện để chạy integration test cho ứng dụng container hoặc image
      Hơi tiếc là các dự án mã nguồn mở kiểu này của Google có vẻ cần được chăm sóc thêm, vì nhiều người từng bảo trì ban đầu đã rời đi. Khi có thể, mình gửi PR và thỉnh thoảng cũng đóng issue. Riêng công cụ test này cực kỳ quý giá để giữ tỉnh táo khi phải xử lý nhiều base image cần duy trì nội bộ