Kaniko: Cách Build Docker Image “Sạch” và Bảo Mật Không Cần Quyền Root

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

Tại sao Docker-in-Docker không còn là lựa chọn số một?

Trong những ngày đầu triển khai CI/CD trên Kubernetes, Docker-in-Docker (DinD) là lựa chọn mặc định của nhiều người. Tuy nhiên, để DinD hoạt động, bạn buộc phải cấp quyền privileged: true cho container. Đây là một lỗ hổng bảo mật nghiêm trọng. Nếu kẻ tấn công chiếm được container build, chúng có thể thoát ra và kiểm soát toàn bộ node vật lý của cụm cluster.

Security Team tại các tập đoàn lớn thường sẽ từ chối ngay lập tức nếu bạn yêu cầu quyền root hoặc truy cập vào /var/run/docker.sock. Kaniko ra đời để giải quyết triệt để bài toán này. Đây là công cụ mã nguồn mở từ Google, cho phép build image từ Dockerfile ngay trong userspace mà không cần Docker daemon.

Kinh nghiệm thực tế từ hệ thống chạy hơn 50 microservices của mình cho thấy: việc chuyển sang Kaniko không chỉ giúp hệ thống an toàn hơn mà còn giảm 35-40% tài nguyên RAM/CPU. Lý do là bạn không còn phải duy trì một Docker Daemon chạy ngầm lãng phí trong mỗi build job.

Triển khai Kaniko: Không cần cài đặt rườm rà

Bạn không cần chạy lệnh apt-get install để có Kaniko. Công cụ này được đóng gói sẵn dưới dạng một Docker image thực thi (executor). Bạn chỉ việc gọi image này trong pipeline là có thể bắt đầu build ngay.

Mình thường ưu tiên sử dụng image gcr.io/kaniko-project/executor:debug. Phiên bản debug này tích hợp sẵn shell (như /busybox/sh). Nó cực kỳ hữu ích khi bạn cần chèn thêm các script bổ trợ hoặc kiểm tra file hệ thống ngay trong quá trình pipeline đang chạy.

Test nhanh Kaniko trên máy cá nhân

Trước khi đưa lên server, hãy thử nghiệm cơ chế của Kaniko ngay tại local bằng lệnh sau:

docker run \
    -v $(pwd):/workspace \
    -v ~/.docker/config.json:/kaniko/.docker/config.json \
    gcr.io/kaniko-project/executor:latest \
    --dockerfile=Dockerfile \
    --context=dir:///workspace \
    --destination=your-registry.com/your-image:v1

Tích hợp vào GitLab CI

Cấu hình cho GitLab CI rất gọn gàng. Bạn không cần setup thêm service Docker phức tạp:

build-image:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:debug
    entrypoint: [""]
  script:
    - /kaniko/executor \
      --context "${CI_PROJECT_DIR}" \
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile" \
      --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"

Tối ưu hiệu suất build để tiết kiệm thời gian

Nếu không cấu hình cache, mỗi lần pipeline chạy sẽ là một cực hình vì phải tải lại toàn bộ layer. Với các dự án Node.js có thư mục node_modules nặng nề, việc tối ưu là bắt buộc.

1. Xác thực với Container Registry

Kaniko cần quyền push image lên Docker Hub, GCR hoặc ECR. Nó sẽ tìm file config.json trong thư mục /kaniko/.docker/. Bạn có thể tạo nhanh file này trong script pipeline để bảo mật thông tin đăng nhập.

{
  "auths": {
    "https://index.docker.io/v1/": {
      "auth": "base64_encoded_token"
    }
  }
}

2. Kích hoạt Layer Caching

Đây là kỹ thuật giúp mình giảm thời gian build từ 7 phút xuống còn chưa đầy 2 phút. Kaniko sẽ lưu các layer đã build thành công lên một registry riêng làm bộ nhớ đệm.

/kaniko/executor \
  --context "${CI_PROJECT_DIR}" \
  --cache=true \
  --cache-repo=your-registry.com/kaniko-cache \
  --destination=your-registry.com/your-app:latest

Khi bật --cache=true, Kaniko sẽ kiểm tra layer hiện tại đã có trên cache-repo chưa. Nếu có, nó sẽ tải về thay vì chạy lại lệnh trong Dockerfile.

Xử lý sự cố và Mẹo thực chiến

Dù mạnh mẽ, Kaniko đôi khi cũng khiến người mới bối rối với một vài lỗi đặc thù.

  • Lỗi Out of Memory (OOM): Kaniko giải nén toàn bộ filesystem vào bộ nhớ để snapshot. Nếu build image chứa dữ liệu lớn (trên 2GB), hãy tăng giới hạn RAM cho Pod chạy build tối thiểu 4GB.
  • Lỗi Permission Denied: Thường do file config.json đặt sai chỗ. Hãy kiểm tra kỹ đường dẫn tuyệt đối là /kaniko/.docker/config.json.
  • Debug sâu: Thêm flag -v=debug để xem chi tiết cách Kaniko quét filesystem. Bạn sẽ phát hiện ra tại sao image của mình lại nặng bất thường ở bước nào.

Một mẹo nhỏ cho người dùng Kubernetes: Hãy sử dụng tham số --digest-file=/dev/termination-log. Pipeline sẽ bắt được chính xác mã SHA của image. Điều này giúp tránh lỗi deploy nhầm version do dùng tag latest vốn rất phổ biến và nguy hiểm.

Làm quen với Kaniko có thể tốn thêm chút thời gian cấu hình ban đầu. Tuy nhiên, sự an tâm về bảo mật và hiệu quả tài nguyên mà nó mang lại là hoàn toàn xứng đáng cho bất kỳ hệ thống production nào.

Share: