Chuyển đến nội dung chính

Docker Buildx: Cách xây dựng ảnh container đa nền tảng

Tìm hiểu cách Docker Buildx mở rộng việc build container truyền thống với hỗ trợ đa nền tảng, chiến lược cache nâng cao và tối ưu hiệu năng. Hướng dẫn này bao quát từ khái niệm cơ bản đến kỹ thuật nâng cao.
· 14 phút đọc

Khám phá cùng AI

Xây dựng container cho nhiều nền tảng nghe có vẻ đáng ngại và tốn thời gian, nhưng bạn sắp thấy rằng thực ra không hề như vậy.

Lệnh docker buildx giải quyết thách thức này bằng cách mở rộng khả năng build của Docker với các tính năng nâng cao như tạo ảnh đa nền tảng, tăng cường cache, và xử lý build song song. Nó tích hợp trực tiếp công cụ build thế hệ mới BuildKit vào Docker CLI. Với lệnh buildx, bạn sẽ tạo ra các ảnh container nhỏ hơn, nhanh hơn và an toàn hơn mà không cần học một bộ công cụ hoàn toàn mới.

Những năm gần đây, Buildx đã trở nên gần như thiết yếu cho các thực hành DevOps tốt và phát triển ứng dụng cloud-native. Nó tinh gọn pipeline CI/CD và giúp bạn cùng đội ngũ triển khai ứng dụng nhất quán trên nhiều đích triển khai đa dạng, từ thiết bị IoT dùng ARM đến các cụm máy chủ đám mây.

> Mới làm quen với Docker? Hướng dẫn thực hành cho người mới bắt đầu của chúng tôi sẽ giúp bạn khởi động ngay.

Trong bài viết này, tôi sẽ hướng dẫn bạn qua các kỹ thuật docker buildx từ cơ bản đến nâng cao.

Tìm hiểu Docker Buildx

Có lẽ bạn đã dùng Docker, nên bạn biết lệnh tiêu chuẩn docker build. Tuy nhiên, sớm muộn gì bạn cũng sẽ thấy nó hạn chế, đặc biệt khi dự án trở nên phức tạp hơn.

> Docker Buildx giả định bạn đã cài Docker. Nếu chưa và đang chạy Linux, hãy làm theo hướng dẫn này để cài đặt dễ dàng.

Docker Buildx mang đến trải nghiệm build được cải thiện mà phù hợp với kiến thức bạn đã có. Nó không phải công cụ riêng cần cài — đã được đóng gói sẵn trong Docker Desktop và Engine từ phiên bản 19.03. Buildx dùng BuildKit ở lớp nền, là builder thế hệ kế tiếp của Docker, viết lại cách ảnh được tạo ra. Bạn sẽ nhận thấy build nhanh hơn, ảnh nhỏ hơn và hỗ trợ nhiều tính năng bổ sung.

Bước chuyển từ docker build sang docker buildx build có vẻ nhỏ — rốt cuộc chỉ thêm một từ — nhưng khả năng bạn nhận được là rất lớn.

Hãy khám phá Buildx thực sự hoạt động thế nào và điều gì khiến nó khác biệt so với builder cũ.

Nền tảng kiến trúc của Buildx

Sự “ảo diệu” của Buildx đến từ thiết kế client-server thông minh.

Khi bạn chạy lệnh Buildx, bạn dùng Docker CLI như một client giao tiếp với BuildKit daemon — thành phần server xử lý công việc nặng. Sự tách biệt này cho phép BuildKit thực hiện những điều builder cũ không làm được, như chạy các giai đoạn build song song thay vì tuần tự. Các chỉ thị trong Dockerfile của bạn không còn phải thực thi lần lượt nữa, điều này cắt giảm đáng kể thời gian build khi có các giai đoạn độc lập.

Mô hình client-server cũng cho phép thực thi build từ xa. Bạn có thể trỏ Docker CLI cục bộ đến một BuildKit từ xa chạy ở bất cứ đâu — trên máy chủ build mạnh, trên đám mây, hoặc trong cụm Kubernetes. Tính linh hoạt này giúp bạn không phải chiếm dụng tài nguyên laptop cho các build khổng lồ hay lo lắng về vấn đề tương thích kiến trúc.

Thiết kế mô-đun của BuildKit cũng cho phép bạn cắm vào các trình phân tích frontend khác nhau. Cú pháp Dockerfile là mặc định, nhưng bạn có thể dùng các định dạng định nghĩa build thay thế nếu phù hợp hơn với quy trình làm việc.

Luồng quy trình build

Khi bạn chạy docker buildx build, CLI sẽ chọn một thể hiện builder, mặc định hoặc do bạn chỉ định. Ngữ cảnh build và Dockerfile của bạn được gửi đến BuildKit daemon, nơi phân tích chỉ thị và tạo một đồ thị có hướng không chu trình (DAG) của các bước build. Khác với builder cũ xử lý tuần tự từng chỉ thị, BuildKit phân tích đồ thị để xác định các bước có thể chạy song song.

Tiếp đó, builder thực thi các bước này với thuật toán cache hiệu quả, thông minh hơn nhiều so với cache theo lớp trước đây. BuildKit theo dõi chính xác đầu vào và đầu ra của từng bước, nhờ đó tránh rebuild không cần thiết khi không có gì liên quan thay đổi. Nó cũng hỗ trợ phân tán build qua nhiều nút worker để xử lý nhanh hơn nữa.

Sau khi build, Buildx có thể xuất kết quả ở nhiều định dạng khác nhau, không chỉ là ảnh Docker. Bạn có thể xuất ra định dạng OCI, thư mục cục bộ, hoặc tarball, thậm chí bỏ qua việc tạo ảnh hoàn chỉnh nếu bạn chỉ muốn kiểm thử quy trình build.

Bạn nói đúng — phần này chắc chắn sẽ hay hơn với nhiều ví dụ thực tế và hình ảnh minh họa cách Buildx hoạt động trong các tình huống đời thực. Dưới đây là cách tôi sẽ bổ sung bằng nhiều ví dụ mã và gợi ý hình ảnh:

Chức năng cốt lõi và tính năng

Docker Buildx không chỉ để build ảnh nhanh hơn, dù chắc chắn nó làm được điều đó. Mục tiêu là mở rộng những gì khả thi với pipeline build của bạn.

Hãy đi sâu vào các tính năng nổi bật khiến Buildx đáng để cân nhắc cho dự án tiếp theo.

> Tìm ý tưởng dự án Docker? 10 ý tưởng này sẽ giúp danh mục DevOps của bạn vào khuôn.

Ứng dụng Python sử dụng

Trong khuôn khổ bài viết, tôi tạo một ứng dụng Python Flask đơn giản. Để làm theo, hãy tạo 3 tệp — app.py, requirements.txt và Dockerfile.

Nội dung cho từng tệp như sau:

app.py

from flask import Flask, render_template_string
import platform
import socket
import psutil
import datetime

app = Flask(__name__)


@app.route("/")
def home():
    html = """
    <!DOCTYPE html>
    <html>
      <head>
        <title>Docker Buildx Python Demo</title>
        <style>
          body {
            
            max-width: 800px;
            
            
          }
          .container {
            border: 1px solid #ddd;
            border-radius: 5px;
            
            background-
          }
          .info {
            
          }
          .platform {
            font-weight: bold;
            
          }
        </style>
      </head>
      <body>
        <h1>Docker Buildx Multi-Platform Demo (Python)</h1>
        <div class="container">
          <div class="info">Hostname: {{ hostname }}</div>
          <div class="info">Platform: <span class="platform">{{ os_platform }} ({{ architecture }})</span></div>
          <div class="info">CPUs: {{ cpu_count }}</div>
          <div class="info">Total Memory: {{ memory_mb }} MB</div>
          <div class="info">Server Time: {{ server_time }}</div>
        </div>
      </body>
    </html>
    """
    return render_template_string(
        html,
        hostname=socket.gethostname(),
        os_platform=platform.system(),
        architecture=platform.machine(),
        cpu_count=psutil.cpu_count(),
        memory_mb=round(psutil.virtual_memory().total / (1024 * 1024)),
        server_time=datetime.datetime.now().isoformat(),
    )


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

requirements.txt

flask==3.1.0
psutil==7.0.0

Dockerfile

FROM python:3.13-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app.py .

EXPOSE 5000

CMD ["python", "app.py"]

Hoàn tất, hãy mở một cửa sổ Terminal mới và chuyển đến thư mục dự án.

Xây dựng ảnh đa nền tảng

Xây ảnh chạy trên nhiều kiến trúc CPU nghe như ác mộng, nhưng Buildx khiến việc này đơn giản đáng ngạc nhiên.

Hãy xem lệnh sau:

docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .

Hình 1 - Sử dụng Docker Buildx

Hình 1 - Sử dụng Docker Buildx

Tóm lại, nó cho phép bạn tạo ảnh cho nhiều kiến trúc đồng thời. Buildx xử lý bằng ba cách thông minh: dùng QEMU để giả lập kiến trúc (cho phép build ảnh ARM trên máy x86), kết nối tới các nút builder native cho từng nền tảng đích, hoặc kết hợp cả hai để tối ưu hiệu năng. Kết quả là một danh sách manifest đa kiến trúc — đôi khi gọi là "fat manifest" — chứa biến thể ảnh cho mỗi nền tảng.

Nếu bạn triển khai lên các môi trường đa dạng như AWS Graviton, cụm Raspberry Pi, hoặc hạ tầng hỗn hợp, hỗ trợ đa nền tảng là tối quan trọng.

Chiến lược cache nâng cao

Buildx hoàn toàn thay đổi cách hoạt động của cache build và nói chung làm build của bạn nhanh hơn.

Hệ thống triển khai chiến lược cache ba tầng, vượt xa cache theo lớp đơn giản của build Docker truyền thống:

  1. Nhúng cache inline: Trước hết, Buildx sử dụng cache inline nhúng trong ảnh, cho phép tận dụng các lớp đã cache từ lần build trước ngay cả ở môi trường mới.
  2. Cache build cục bộ: Thứ hai, nó hỗ trợ cache build cục bộ được quản lý thông minh dựa trên đầu vào của chỉ thị build thay vì chỉ dựa vào thứ tự.
  3. Cache dựa trên registry: Thứ ba, nó cung cấp cache dựa trên registry cho phép chia sẻ cache build giữa các máy, hoàn hảo cho pipeline CI/CD hoặc đội ngũ phân tán.

Với ứng dụng Python của chúng ta, hãy xem cách dùng cache cục bộ:

# Tạo thư mục cho cache cục bộ
mkdir -p buildx-cache

# Lần build đầu - xuất cache ra thư mục cục bộ
docker buildx build --cache-to type=local,dest=./buildx-cache -t myapp:latest .

# Thực hiện thay đổi nhỏ trong app.py
echo "# Small comment change" >> app.py

# Lần build thứ hai - dùng cache cục bộ
docker buildx build --cache-from type=local,src=./buildx-cache -t myapp:latest .

Lần build thứ hai sẽ nhanh hơn nhiều vì tái sử dụng các lớp đã cache từ lần đầu.

Hình 2 - Chiến lược cache cục bộ

Hình 2 - Chiến lược cache cục bộ

Bạn cũng có thể dùng cache inline, nhúng siêu dữ liệu cache ngay trong ảnh:

docker buildx build --cache-to type=inline -t myapp:latest .

Bạn có thể cấu hình các backend cache này với các cờ đơn giản như --cache-to và --cache-from, trỏ đến thư mục cục bộ, kho registry, hoặc thậm chí các dịch vụ cache chuyên biệt. Tính linh hoạt này giúp build luôn nhanh ở các môi trường khác nhau mà không đánh đổi tính tái lập.

Tính năng bảo mật

Buildx có các công cụ giúp bạn bớt bận tâm về bảo mật.

Giả sử ứng dụng Python của bạn cần truy cập một API thời tiết trong quá trình build. Thay vì hardcode API key trong Dockerfile, bạn có thể dùng secrets cho quá trình build:

# Lưu API key vào tệp cục bộ
echo "abc123yourweatherapikey" > ./api_key.txt

# Build với secret
docker buildx build --secret id=weather_api_key,src=./api_key.txt -t myapp:latest .

Sau đó trong Dockerfile, bạn có thể truy cập secret chỉ khi cần:

FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
# Tạo tệp cấu hình bằng secret tại thời điểm build
RUN --mount=type=secret,id=weather_api_key \
    echo "WEATHER_API_KEY=$(cat /run/secrets/weather_api_key)" > .env
EXPOSE 5000
CMD ["python", "app.py"]

Bạn có thể xác minh API key không nằm trong ảnh cuối bằng cách kiểm tra lịch sử ảnh hoặc chạy:

docker run --rm myapp:latest cat .env

Hình 3 - Quản lý biến môi trường

Hình 3 - Quản lý biến môi trường

Trong app.py, bạn có thể nạp API key như sau:

import os
from dotenv import load_dotenv

load_dotenv()  # Load variables from .env file
api_key = os.getenv("WEATHER_API_KEY", "")
# ...

Cách tiếp cận này nghĩa là API key nhạy cảm của bạn chỉ khả dụng trong bước build cụ thể nơi cần đến, nhưng không bị lưu trong bất kỳ lớp ảnh nào. Bất kỳ ai kéo ảnh của bạn cũng không thể trích xuất API key, ngay cả khi họ kiểm tra các lớp ảnh.

Để tăng bảo mật, bạn cũng có thể dùng container build tạm thời sẽ tự động bị xóa sau khi build:

docker buildx build --secret id=weather_api_key,src=./api_key.txt --rm -t myapp:latest .

Cờ --rm đảm bảo mọi container trung gian được tạo trong quá trình build sẽ bị xóa, càng giảm rủi ro rò rỉ thông tin xác thực.

Cấu hình vận hành

Thiết lập Buildx cho quy trình làm việc của bạn chỉ cần vài lệnh, nhưng hiểu các tùy chọn sẽ giúp bạn khai thác tối đa.

Hãy xem cách bạn có thể cấu hình và quản lý Buildx trong môi trường cục bộ để phù hợp với nhu cầu cụ thể.

Quản lý thể hiện builder

Docker Buildx dùng khái niệm "builder" — các BuildKit instance riêng với năng lực và cấu hình khác nhau. Bạn có thể tạo nhiều builder cho các mục đích khác nhau.

Trước tiên, hãy xem bạn đã có những builder nào:

docker buildx ls

Bạn sẽ thấy đầu ra tương tự như sau:

Hình 4 - Các builder hiện có

Hình 4 - Các builder hiện có

Để tạo một builder mới, chạy các lệnh sau:

# Tạo builder mới
docker buildx create --name mybuilder

# Chuyển sang dùng builder đó
docker buildx use mybuilder

# Khởi động builder
docker buildx inspect --bootstrap

Bạn có thể xác minh nó đang hoạt động với:

# Kiểm tra trạng thái
docker buildx ls

Hình 5 - Chuyển sang builder tùy chỉnh

Hình 5 - Chuyển sang builder tùy chỉnh

Nếu cần xóa một builder, chỉ cần chạy:

docker buildx rm mybuilder

Xử lý đầu ra

Buildx cung cấp các tùy chọn linh hoạt cho ảnh bạn build. Bạn có thể nạp trực tiếp vào Docker daemon cục bộ, xuất ra tarball, hoặc lưu vào thư mục cục bộ.

Hãy xem cách dùng các tùy chọn này với ứng dụng Python của chúng ta:

# Nạp ảnh trực tiếp vào Docker (mặc định)
docker buildx build --load -t myapp:latest .

# Xuất ảnh thành tarball
docker buildx build --output type=docker,dest=myapp.tar -t myapp:latest .

# Lưu nội dung ảnh vào thư mục cục bộ
docker buildx build --output type=local,dest=./image-output -t myapp:latest .

Sau khi xuất tarball, bạn có thể nạp vào Docker bằng:

docker load < myapp.tar

Hình 6 - Nạp ảnh từ tarball

Hình 6 - Nạp ảnh từ tarball

Đầu ra là thư mục cục bộ đặc biệt hữu ích để kiểm tra. Hãy xem những gì được tạo:

ls -la ./image-output

Bạn sẽ thấy hệ thống tệp ảnh thô:

Hình 7 - Nội dung export thư mục cục bộ

Hình 7 - Nội dung export thư mục cục bộ

Bạn thậm chí có thể chạy riêng các giai đoạn build mà không tạo ảnh cuối. Rất hữu ích để debug hoặc kiểm thử bước build:

# Tạo một Dockerfile đa giai đoạn
cat > Dockerfile.multi << 'EOF'
FROM python:3.13-slim AS base
WORKDIR /app
COPY requirements.txt .

FROM base AS dev-deps
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install pytest

FROM base AS prod-deps
RUN pip install --no-cache-dir -r requirements.txt

FROM prod-deps AS final
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]
EOF

# Chỉ build giai đoạn dev-deps và xuất hệ thống tệp của nó
docker buildx build --file Dockerfile.multi --target dev-deps --output type=local,dest=./dev-deps-output .

Giờ bạn có thể kiểm tra các gói đã cài trong môi trường dev:

cat ./dev-deps-output/usr/local/lib/python3.13/site-packages/pytest/__init__.py

Hình 8 - Nội dung tệp từ giai đoạn dev-deps

Hình 8 - Nội dung tệp từ giai đoạn dev-deps

Tóm lại, các tùy chọn đầu ra này cho bạn toàn quyền kiểm soát nơi ảnh đã build sẽ đến, dù bạn đang debug cục bộ hay chuẩn bị chia sẻ ảnh với đội ngũ.

Tình huống sử dụng nâng cao

Từ đầu đến giờ, tôi đã giới thiệu các lệnh và tình huống sử dụng Buildx cơ bản. Buildx còn làm được nhiều hơn thế, với một số tính năng không thể triển khai bằng builder cổ điển.

Hãy khám phá một số kỹ thuật nâng cao để đưa quy trình container hóa của bạn lên cấp độ tiếp theo.

Tối ưu build đa giai đoạn

Build đa giai đoạn là một trong những tính năng mạnh nhất của Docker để tạo ảnh hiệu quả, và Buildx còn khiến chúng tốt hơn nữa.

Để minh họa, hãy tạo một ứng dụng Python tối ưu hóa với nhiều giai đoạn:

# Dockerfile.optimized
FROM python:3.13-slim AS base
WORKDIR /app
COPY requirements.txt .

FROM base AS builder
RUN pip install --no-cache-dir --target=/install -r requirements.txt

FROM base AS linter
COPY --from=builder /install /usr/local/lib/python3.13/site-packages
COPY app.py .
RUN pip install pylint && pylint app.py || exit 0

FROM base AS tester
COPY --from=builder /install /usr/local/lib/python3.9/site-packages
COPY app.py .
RUN pip install pytest && python -m pytest app.py -v || exit 0

FROM python:3.13-alpine AS final
WORKDIR /app
COPY --from=builder /install /usr/local/lib/python3.13/site-packages
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]

Với Buildx, bạn có thể build hiệu quả hơn:

docker buildx build --file Dockerfile.optimized -t myapp:optimized --load .

Hình 9 - Build đa giai đoạn

Hình 9 - Build đa giai đoạn

Vậy điều gì đặc biệt? Buildx xử lý các giai đoạn độc lập song song. Trong khi builder cũ thực thi từng giai đoạn tuần tự, Buildx nhận ra rằng các giai đoạn linter và tester không phụ thuộc nhau và build đồng thời.

Một lợi ích nữa của tối ưu hóa build là giảm kích thước tệp. Bạn có thể kiểm tra kích thước ảnh bằng cách chạy:

docker images myapp

Bạn sẽ thấy tương tự như sau:

Hình 10 - Kích thước ảnh Docker

Hình 10 - Kích thước ảnh Docker

Ảnh cuối dựa trên alpine nhỏ hơn nhiều.

Tích hợp pipeline CI/CD

Dù bạn đang làm việc cục bộ, bạn vẫn có thể thiết lập cấu hình Buildx phản chiếu môi trường CI/CD.

Đầu tiên, tạo tệp .dockerignore để giữ bản build sạch:

.git
__pycache__
*.pyc
*.pyo
*.pyd
.Python
env
venv
*.so
.coverage
htmlcov

Sau đó tạo script build mô phỏng những gì pipeline CI có thể làm:

#!/bin/bash
# build.sh - Mô phỏng CI/CD cục bộ

echo "Starting CI/CD build process..."

# Thiết lập builder với hỗ trợ giả lập
echo "Setting up builder..."
docker buildx create --name cibuilder --use || true
docker buildx inspect --bootstrap

# Chạy lint
echo "Running lint stage..."
docker buildx build --file Dockerfile.optimized --target linter .

# Chạy test
echo "Running test stage..."
docker buildx build --file Dockerfile.optimized --target tester .

# Build cho nhiều nền tảng
echo "Building multi-platform image..."
docker buildx build --file Dockerfile.optimized \
  --platform linux/amd64,linux/arm64 \
  --tag myapp:$(date +%Y%m%d) \
  --tag myapp:latest \
  --load \
  --progress=plain \
  .

echo "Build process complete!"

Nói dễ hiểu, script này làm các việc sau:

  • Tạo builder dành riêng cho CI/CD.
  • Chạy giai đoạn lint.
  • Chạy giai đoạn kiểm thử.
  • Build ảnh đa nền tảng cuối cùng với thẻ phiên bản.

Giờ đến phần thú vị — cấp quyền thực thi và chạy script:

chmod +x build.sh
./build.sh

Chỉnh sửa cục bộ

Một điểm đau thường gặp khi làm việc với Docker là mỗi lần bạn thay đổi mã nguồn, bạn phải rebuild ảnh và chạy lại container. Rất tốn thời gian.

Tin vui là: cho phát triển cục bộ với vòng lặp nhanh hơn, bạn có thể tạo phiên bản dành cho dev:

# Dockerfile.dev
FROM python:3.13-slim
WORKDIR /app

RUN pip install flask psutil python-dotenv

# Cài công cụ phát triển
RUN pip install pytest pylint watchdog

# Gắn mã nguồn lúc chạy thay vì copy
CMD ["python", "app.py"]

Chạy với volume mount để tự động nạp lại mã:

docker buildx build -f Dockerfile.dev -t myapp:dev --load .
docker run -it --rm -p 5000:5000 -v $(pwd):/app myapp:dev

Giờ bạn có thể chỉnh sửa tệp app.py cục bộ, và thay đổi sẽ lập tức phản ánh trong container đang chạy!

Tiếp theo, hãy nói về hiệu năng.

Cân nhắc về hiệu năng

Không ai thích quy trình phát triển chậm chạp, và sức mạnh song song hóa của Docker Buildx có thể giúp ích.

Hãy khám phá cách tối ưu build và tận dụng các tính năng hiệu năng của Buildx để tạo ảnh nhanh hơn.

Kỹ thuật song song hóa build

Một trong những lợi thế lớn nhất của Buildx là khả năng build các giai đoạn song song. Builder truyền thống thực thi từng bước tuần tự, còn Buildx phân tích Dockerfile và xác định các bước có thể chạy đồng thời.

Để minh họa, tôi sẽ dùng hai tệp — Dockerfile.standard và Dockerfile.parallel. Nội dung như sau:

Dockerfile.standard

FROM python:3.13-slim
WORKDIR /app

# Phụ thuộc hệ thống
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    g++ \
    && rm -rf /var/lib/apt/lists/*

# Phụ thuộc Python
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Mã ứng dụng
COPY app.py .

# Linting
RUN pip install pylint && pylint app.py || true

EXPOSE 5000
CMD ["python", "app.py"]

Dockerfile.parallel

FROM python:3.13-slim AS python-base
WORKDIR /app

# Giai đoạn độc lập cài phụ thuộc hệ thống
FROM python-base AS system-deps
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    g++ \
    && rm -rf /var/lib/apt/lists/*

# Giai đoạn độc lập cài phụ thuộc Python
FROM python-base AS python-deps
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Giai đoạn độc lập phân tích mã tĩnh
FROM python-deps AS linting
COPY app.py .
RUN pip install pylint && pylint app.py || true

# Giai đoạn cuối kết hợp phụ thuộc
FROM python-base AS final
# Sao chép từ giai đoạn phụ thuộc hệ thống
COPY --from=system-deps /usr/bin/gcc /usr/bin/gcc
# Sao chép từ giai đoạn phụ thuộc Python
COPY --from=python-deps /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]

Hãy đo mức cải thiện thời gian build nhờ cấu trúc song song này:

# Đo thời gian build tuần tự chuẩn
time docker build -t myapp:standard -f Dockerfile.standard .

# Đo thời gian build tối ưu song song với Buildx
time docker buildx build --load -t myapp:parallel -f Dockerfile.parallel .

Tham khảo: build chuẩn mất 18,48 giây trong khi build song song chỉ mất 1,17 giây!

Để hiệu năng tốt hơn nữa, bạn có thể dùng các cờ --cache-from và --cache-to để tận dụng cache đĩa cục bộ:

# Lần build đầu - tạo cache
docker buildx build --load -t myapp:latest --cache-to type=local,dest=./buildcache .

# Các lần build sau - dùng cache
docker buildx build --load -t myapp:latest --cache-from type=local,src=./buildcache .

Bạn cũng có thể giới hạn kích thước context với tệp .dockerignore kỹ lưỡng:

# Tạo .dockerignore đầy đủ
cat > .dockerignore << 'EOF'
.git
.github
.dockerignore
.pytest_cache
__pycache__
*.pyc
*.pyo
*.pyd
.Python
venv
env
node_modules
.coverage
htmlcov
.DS_Store
EOF

Nói ngắn gọn, bằng cách cấu trúc Dockerfile với tư duy song song và tận dụng cache nâng cao của Buildx, bạn sẽ dành ít thời gian chờ build hơn và nhiều thời gian phát triển tính năng hơn.

Tích hợp hệ sinh thái

Docker Buildx không tồn tại độc lập. Nó được xây dựng để tích hợp liền mạch với các công cụ khác trong môi trường phát triển của bạn.

Hãy xem Buildx phối hợp với các công cụ dev cục bộ thế nào và khiến quy trình container của bạn hiệu quả hơn.

Cụm build Kubernetes

Kubernetes cung cấp khả năng mạnh mẽ để chạy các tác vụ Docker Buildx phân tán trên cả cụm. Khi tích hợp Buildx với Kubernetes, bạn có thể đạt build nhanh hơn và ổn định hơn, mở rộng theo nhu cầu dự án.

> Bạn mới làm quen Kubernetes? Bài viết Kubernetes vs Docker: Những khác biệt mọi lập trình viên nên biết là điểm dừng tiếp theo.

Dùng Kubernetes cho hạ tầng build mang lại vài lợi thế:

  1. Tự động mở rộng: Kubernetes có thể mở rộng các nút builder theo nhu cầu, phân bổ tài nguyên hiệu quả trên cụm. Bạn còn có thể đặt quy tắc autoscaling theo mức sử dụng CPU.
  2. Tối ưu tài nguyên: Lập lịch của Kubernetes đảm bảo build của bạn nhận tài nguyên cần thiết mà không quá tải từng nút. Bạn có thể đặt giới hạn và yêu cầu tài nguyên để đảm bảo hiệu năng ổn định.
  3. Khả dụng cao: Bằng cách phân tán BuildKit qua nhiều nút, hạ tầng build của bạn vẫn sẵn sàng ngay cả khi một số nút gặp sự cố.
  4. Môi trường nhất quán: Mọi thành viên kết nối tới cùng hạ tầng build, loại bỏ vấn đề “chạy được trên máy tôi”.
  5. Thực thi song song: Các build phức tạp với nhiều giai đoạn có thể chạy song song trên nhiều nút, giảm đáng kể thời gian build. Một dự án có thể mất 15 phút build cục bộ có thể hoàn thành trong 3-4 phút khi phân tán.

Hãy coi đây là phần “lý thuyết” hơn, vì đi sâu vào Kubernetes tự nó đã là một chủ đề nâng cao.

Để bắt đầu, tạo tệp buildkit-deployment.yaml với nội dung sau:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: buildkit
  namespace: buildkit
spec:
  replicas: 3
  selector:
    matchLabels:
      app: buildkit
  template:
    metadata:
      labels:
        app: buildkit
    spec:
      containers:
      - name: buildkit
        image: moby/buildkit:latest
        args:
        - --addr
        - tcp://0.0.0.0:1234
        ports:
        - containerPort: 1234
        securityContext:
          privileged: true
---
apiVersion: v1
kind: Service
metadata:
  name: buildkit
  namespace: buildkit
spec:
  type: ClusterIP
  ports:
  - port: 1234
    targetPort: 1234
  selector:
    app: buildkit

Bước tiếp theo là áp dụng tệp này lên cụm Kubernetes của bạn:

kubectl create namespace buildkit
kubectl apply -f buildkit-deployment.yaml

Cuối cùng, kết nối từ máy cục bộ đến triển khai này:

docker buildx create --name k8s-builder \
  --driver remote \
  --driver-opt endpoint=tcp://<cluster-ip>:1234 \
  --use

Vậy là xong, bạn đã sẵn sàng!

Hỗ trợ plugin IDE

Các IDE như Visual Studio Code cung cấp tích hợp tuyệt vời với Docker Buildx thông qua tiện ích mở rộng Docker. Sự tích hợp này giúp bạn quản lý quy trình Buildx trực tiếp từ môi trường phát triển.

Để bắt đầu với Docker Buildx trong VS Code, hãy cài tiện ích "Docker" từ marketplace của VS Code.

Sau khi cài, bạn sẽ có một số tính năng riêng cho Buildx:

  • Bấm chuột phải vào bất kỳ Dockerfile để thấy menu ngữ cảnh với tùy chọn "Build Image..." hỗ trợ Buildx.
  • Truy cập build args, mục tiêu nền tảng, và tùy chọn đầu ra qua giao diện.
  • Khả năng quản lý và chuyển đổi giữa các thể hiện builder khác nhau.
  • Tích hợp với terminal của VS Code để chạy các lệnh Buildx phức tạp.

Hình 12 - Tiện ích Docker cho VSCode

Hình 11 - Tiện ích Docker cho VSCode

Dưới đây là ví dụ tùy chỉnh tác vụ VS Code để dùng Buildx bằng cách tạo tệp .vscode/tasks.json:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Docker: Buildx Build",
      "type": "shell",
      "command": "docker buildx build --load -t ${input:imageName} .",
      "group": {
        "kind": "build",
        "isDefault": true
      }
    },
    {
      "label": "Docker: Buildx Multi-Platform",
      "type": "shell",
      "command": "docker buildx build --platform linux/amd64,linux/arm64 -t ${input:imageName} ."
    }
  ],
  "inputs": [
    {
      "id": "imageName",
      "description": "Image name (with tag):",
      "default": "myapp:latest",
      "type": "promptString"
    }
  ]
}

Với cấu hình này, bạn có thể truy cập nhanh các lệnh Buildx phổ biến từ menu Tasks của VS Code (Terminal > Run Task). Tiện ích cũng cung cấp tô sáng cú pháp cho Dockerfile và tự động hoàn thành cho các lệnh Docker thường dùng, giúp quy trình Buildx năng suất hơn.

Khắc phục sự cố và gỡ lỗi

Mọi công cụ phát triển đôi khi (quá thường xuyên) đều cần khắc phục sự cố, và Docker Buildx không ngoại lệ. Phần này, tôi sẽ hướng dẫn bạn qua một vài vấn đề phổ biến để bạn tự chẩn đoán nhanh và quay lại công việc.

Vấn đề thường gặp và cách giải quyết

Khi làm việc với Buildx, bạn có thể gặp một số thách thức phổ biến. Dưới đây là những vấn đề thường gặp và cách xử lý:

  • Tạo builder thất bại. Nếu gặp lỗi khi tạo builder với docker buildx create, hãy kiểm tra phiên bản Docker:
docker version

Buildx yêu cầu Docker 19.03 trở lên. Nếu bạn dùng phiên bản cũ hơn, hãy nâng cấp Docker để truy cập các tính năng Buildx.

Với lỗi "no such plugin", hãy đảm bảo Buildx được cài đúng bằng cách chạy:

docker buildx version
  • Lỗi build đa nền tảng. Khi build cho nhiều nền tảng gặp lỗi như "exec format error" hoặc "no matching manifest", hãy kiểm tra QEMU đã cài chưa:
docker buildx inspect --bootstrap

Nếu cần, cài các trình giả lập nền tảng:

docker run --privileged --rm tonistiigi/binfmt --install all
  • Vấn đề liên quan đến cache. Với các vấn đề cache, hãy thử dọn cache build cục bộ:
# Xóa cache của builder cụ thể
docker buildx prune -b mybuilder

# Xóa toàn bộ cache build
docker buildx prune --all

> Chính xác lệnh Docker prune là gì? Tìm hiểu với hàng loạt ví dụ thực hành.

  • Sự cố kết nối BuildKit daemon. Nếu thấy "failed to solve" hoặc lỗi kết nối, hãy khởi động lại builder:
docker buildx rm mybuilder
docker buildx create --name mybuilder --use
docker buildx inspect --bootstrap
  • Vấn đề hiệu năng. Với build chậm, hãy bật đầu ra debug để xác định nút thắt:
docker buildx build --progress=plain --no-cache .

Đầu ra chi tiết này giúp xác định giai đoạn build nào tốn thời gian nhất, cho phép bạn tối ưu Dockerfile tương ứng.

  • Lỗi với lệnh "Load". Nếu gặp lỗi "error: docker exporter does not currently support exporting manifest lists" khi dùng --load với build đa nền tảng, hãy nhớ rằng việc nạp đồng thời nhiều nền tảng vào Docker daemon chưa được hỗ trợ. Thay vào đó:
# Build cho nền tảng hiện tại và nạp vào
docker buildx build --platform linux/amd64 --load -t myapp:latest .
  • Thực hành gỡ lỗi. Với các vấn đề phức tạp hơn, những cách sau sẽ giúp bạn:
# Bật log debug của BuildKit
BUILDKIT_DEBUG=1 docker buildx build .

# Kiểm tra trạng thái nội bộ của builder
docker buildx inspect

# Kiểm tra yêu cầu hệ thống
docker info

# Với lỗi ở giai đoạn cụ thể, chỉ build đến giai đoạn đó
docker buildx build --target problem-stage .

# Xác minh Docker context của bạn
docker context ls

Bằng cách làm việc có hệ thống qua các bước khắc phục này, bạn có thể giải quyết hầu hết vấn đề của Buildx và duy trì quy trình build container hiệu quả.

Tổng kết hướng dẫn Docker Buildx

Chúng ta đã bao quát rất nhiều nội dung trong bài viết Docker Buildx này! Bạn đã thấy công cụ mạnh mẽ này có thể khiến quá trình build container nhanh hơn và linh hoạt hơn thế nào.

Hãy nhớ những lợi ích chính: Bạn có thể build ảnh cho nhiều nền tảng chỉ với một lệnh, tăng tốc build với cache nâng cao, và giữ ảnh an toàn nhờ quản lý secrets đúng cách. Cải thiện hiệu năng là có thật, đặc biệt khi bạn cấu trúc Dockerfile để tận dụng build song song.

Tôi dùng nó liên tục trên Macbook chip M vì không phải mọi ảnh đều có sẵn cho ARM.

Dù bạn là nhà phát triển độc lập hay thành viên của một đội ngũ lớn, Buildx mang đến các công cụ phù hợp với quy trình làm việc của bạn. Bạn có thể chạy build cục bộ, phân tán qua các container, hoặc thậm chí mở rộng lên cụm Kubernetes khi nhu cầu tăng.

Để tìm hiểu thêm về Docker và Docker Buildx, tôi khuyến nghị đăng ký các khóa học sau trên DataCamp:

Dario Radečić

Tác giả

Dario Radečić

Chuyên gia Khoa học Dữ liệu Cấp cao, làm việc tại Croatia. Tác giả Công nghệ Hàng đầu với hơn 700 bài viết đã xuất bản, đạt trên 10 triệu lượt xem. Tác giả cuốn sách Tự động hóa Machine Learning với TPOT.

Chủ đề

Liên quan