Feb 2026 • Docker Guide

Docker Multi-Platform Builds

Build ครั้งเดียว ใช้ได้ทุก Architecture (ARM64 + AMD64)

รองรับ Apple Silicon M1/M2/M3 และ ARM cloud instances (AWS Graviton, Azure Ampere) ลดต้นทุนได้มาก!

Docker
ARM64
AMD64
Apple Silicon

1. บทนำ

Docker Multi-Platform Builds คือความสามารถในการสร้าง Docker images ครั้งเดียวสำหรับหลาย CPU architectures โดยใช้ Docker Buildx และ BuildKit ทำให้นักพัฒนาสามารถสร้าง container images ที่รันได้ทั้งบน:

  • linux/amd64 - Intel/AMD x86_64 (PC, Server ทั่วไป)
  • linux/arm64 - ARM 64-bit (Apple Silicon, AWS Graviton, Raspberry Pi 4)
  • linux/arm/v7 - ARM 32-bit (Raspberry Pi 3)

ก่อนหน้านี้ ถ้าคุณใช้ Mac M1/M2/M3 และ build image บนเครื่อง คุณจะได้ ARM64 image ซึ่งรันบน Intel server ไม่ได้ แต่ด้วย Multi-Platform Builds คุณสามารถ build ทั้งสองแบบพร้อมกันได้!

2. ทำไมต้อง Multi-Platform?

Apple Silicon (M1/M2/M3)

ปัจจุบันนักพัฒนาหลายคนใช้ Mac ที่มี Apple Silicon ซึ่งเป็น ARM architecture แต่ production servers ส่วนใหญ่ยังเป็น Intel/AMD

  • Build บน Mac รันบน Server ได้
  • ไม่ต้องมีเครื่องหลายเครื่อง

ลด Cost บน Cloud

ARM instances ราคาถูกกว่า Intel/AMD แต่ต้องมี ARM-compatible images

  • AWS Graviton ถูกกว่า ~20%
  • Azure Ampere Altra ประหยัดกว่า
  • Google Cloud Tau T2A ราคาดี

ประสิทธิภาพดีกว่า

ARM processors มี performance per watt ที่ดีกว่า ทำให้เหมาะกับงานบางประเภท

  • Web servers ทำงานได้ดี
  • Microservices เหมาะสม
  • Edge computing

Image เดียว ใช้ได้ทุกที่

Docker Manifest Lists ทำให้ pull image เดียวกันได้บนทุก platform อัตโนมัติ

  • docker pull myapp:latest ใช้ได้ทุกเครื่อง
  • ไม่ต้องระบุ architecture

3. สิ่งที่ต้องเตรียม

บนเครื่อง Local

Docker Desktop 4.x+

หรือ Docker Engine 23.0+ บน Linux

docker --version

Docker Buildx

มาพร้อม Docker Desktop หรือติดตั้งแยก

docker buildx version

QEMU (Optional)

สำหรับ cross-platform emulation

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

Registry Account

Docker Hub, GitHub Container Registry, หรือ ECR

docker login

บน CI/CD (GitHub Actions)

GitHub Actions รองรับ native ARM64 runners แล้ว ไม่ต้องใช้ QEMU emulation ทำให้ build เร็วขึ้นมาก

4. สถาปัตยกรรม Multi-Platform Build

Docker Multi-Platform Build Flow Source Code Dockerfile Application Docker Buildx Multi-Platform Builder Cross-Compilation QEMU Emulation linux/amd64 Intel/AMD x86_64 linux/arm64 Apple Silicon/AWS Graviton linux/arm/v7 Raspberry Pi 3 Manifest List (Index) Multi-arch Image myapp:latest Container Registry Docker Hub / ECR / GCR Legend: x86_64 (Intel/AMD) ARM64 (Apple/AWS) ARMv7 (Raspberry Pi)

วิธีการทำงาน

  1. Docker Buildx รับ Dockerfile และ build สำหรับแต่ละ platform
  2. ใช้ QEMU emulation สำหรับ cross-compilation (เช่น build ARM64 บน AMD64 machine)
  3. สร้าง images แยกสำหรับแต่ละ architecture
  4. รวมเป็น Manifest List (Index) ที่อ้างอิงแต่ละ image
  5. Push ไป Registry เป็น single tag (myapp:latest)
  6. เมื่อ pull Docker จะเลือก image ที่เหมาะสมกับ architecture อัตโนมัติ

5. ขั้นตอนการใช้งาน

1

ตรวจสอบ Docker Buildx

ตรวจสอบว่า Docker Buildx พร้อมใช้งานหรือไม่

Terminal
# ตรวจสอบ version
docker buildx version

# แสดง builders ที่มี
docker buildx ls
2

สร้าง Multi-Platform Builder

สร้าง builder instance ใหม่ที่รองรับ multi-platform

Terminal
# สร้าง builder ใหม่
docker buildx create --name mybuilder --use

# ตรวจสอบ builder
docker buildx inspect --bootstrap

# Output ที่ควรเห็น:
# Name:   mybuilder
# Driver: docker-container
# Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
3

เปิดใช้งาน QEMU (Optional)

ถ้าต้องการ cross-compile ให้ติดตั้ง QEMU support

Terminal
# ติดตั้ง QEMU support (รันครั้งเดียว)
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

# หลังจากนี้จะสามารถ build ARM64 บน AMD64 machine ได้

หมายเหตุ: Docker Desktop บน Mac/Windows มี QEMU built-in แล้ว ไม่ต้องรันคำสั่งนี้

4

Build Multi-Platform Image

Build image สำหรับหลาย platforms พร้อมกัน

Terminal
# Build สำหรับ AMD64 และ ARM64 พร้อมกัน
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myapp:latest \
  --load \
  .

# ถ้าต้องการ push ไป registry ด้วย
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t username/myapp:latest \
  --push \
  .
5

ตรวจสอบ Multi-Platform Image

ตรวจสอบ manifest และ supported platforms

Terminal
# ตรวจสอบ manifest ของ image
docker buildx imagetools inspect username/myapp:latest

# Output ที่ควรเห็น:
# Name:      username/myapp:latest
# MediaType: application/vnd.docker.distribution.manifest.list.v2+json
# Digest:    sha256:abc123...
#
# Manifests:
#   Name:      linux/amd64
#   Digest:    sha256:def456...
#   Name:      linux/arm64
#   Digest:    sha256:ghi789...

6. ตัวอย่างโค้ด

Dockerfile สำหรับ Multi-Platform

Dockerfile ที่รองรับทุก architecture โดยอัตโนมัติ

Dockerfile
# syntax=docker/dockerfile:1

# ใช้ TARGETPLATFORM และ TARGETARCH ที่ Docker กำหนดให้อัตโนมัติ
FROM --platform=$TARGETPLATFORM node:20-alpine

WORKDIR /app

# ติดตั้ง dependencies (cache layer)
COPY package*.json ./
RUN npm ci --only=production

# Copy source code
COPY . .

# Build arguments สำหรับ architecture-specific settings
ARG TARGETARCH
ARG TARGETPLATFORM

# แสดง architecture ที่กำลัง build
RUN echo "Building for ${TARGETPLATFORM} (${TARGETARCH})"

# Expose port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

# Start application
CMD ["node", "server.js"]

Build Arguments ที่ใช้ได้

Variable Example Value Description
TARGETPLATFORM linux/arm64 Full platform string
TARGETARCH arm64 Architecture only
TARGETOS linux OS only
TARGETVARIANT v7 Variant (if any)
BUILDPLATFORM linux/amd64 Host platform

Docker Bake (Advanced)

ใช้ Docker Bake สำหรับ build configuration ที่ซับซ้อน

docker-bake.hcl
// docker-bake.hcl

variable "REGISTRY" {
  default = "docker.io"
}

variable "IMAGE_NAME" {
  default = "myapp"
}

variable "TAG" {
  default = "latest"
}

group "default" {
  targets = ["app"]
}

target "app" {
  context    = "."
  dockerfile = "Dockerfile"

  platforms = [
    "linux/amd64",
    "linux/arm64",
    "linux/arm/v7"
  ]

  tags = [
    "${REGISTRY}/${IMAGE_NAME}:${TAG}",
    "${REGISTRY}/${IMAGE_NAME}:${TAG}-${timestamp()}"
  ]

  cache-from = ["type=registry,ref=${REGISTRY}/${IMAGE_NAME}:cache"]
  cache-to   = ["type=registry,ref=${REGISTRY}/${IMAGE_NAME}:cache,mode=max"]

  labels = {
    "org.opencontainers.image.source" = "https://github.com/user/repo"
    "org.opencontainers.image.title"   = "My App"
  }
}

รันด้วย: docker bake

7. CI/CD Integration

GitHub Actions

Workflow สำหรับ build และ push multi-platform images

.github/workflows/docker.yml
name: Build and Push Multi-Platform Docker Image

on:
  push:
    branches: [main]
    tags: ['v*']
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to Container Registry
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata for Docker
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          sbom: true
          provenance: true

GitLab CI/CD

.gitlab-ci.yml
variables:
  DOCKER_TLS_CERTDIR: ""
  DOCKER_HOST: tcp://docker:2375

stages:
  - build

build-multiarch:
  stage: build
  image: docker:24
  services:
    - name: docker:24-dind
      command: ["--experimental"]
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker buildx create --use --name mybuilder
  script:
    - |
      docker buildx build \
        --platform linux/amd64,linux/arm64 \
        --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA \
        --tag $CI_REGISTRY_IMAGE:latest \
        --push \
        .
  only:
    - main

8. แก้ไขปัญหาที่พบบ่อย

Error: "multiple platforms feature is currently not supported"

ปัญหานี้เกิดเมื่อใช้ default builder ที่ไม่รองรับ multi-platform

✅ วิธีแก้:

# สร้าง builder ใหม่ที่รองรับ multi-platform
docker buildx create --name mybuilder --use --driver docker-container
docker buildx inspect --bootstrap

Build ช้ามากเมื่อใช้ QEMU emulation

QEMU emulation ทำให้ build ARM64 บน AMD64 machine ช้าลง 10-50 เท่า

✅ วิธีแก้:

  • ใช้ GitHub Actions ARM64 runners (native build)
  • ใช้ Docker Bake กับ remote builders
  • เลี่ยงใช้ emulation ใน production builds

บาง packages ไม่รองรับ ARM64

Native dependencies บางตัวอาจไม่มี ARM64 build

✅ วิธีแก้:

# ใช้ conditional installation ใน Dockerfile
ARG TARGETARCH
RUN if [ "$TARGETARCH" = "arm64" ]; then \
      apk add --no-cache some-arm-package; \
    else \
      apk add --no-cache some-amd-package; \
    fi

Cannot push to registry - "denied: requested access to the resource is denied"

ต้อง login ก่อน push ไป registry

✅ วิธีแก้:

# Login ก่อน push
docker login

# หรือสำหรับ GitHub Container Registry
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

สรุป

สิ่งที่คุณได้เรียนรู้:

  • วิธีสร้าง Multi-Platform Builder
  • Build images สำหรับ AMD64 และ ARM64
  • ใช้ Docker Buildx และ Bake
  • Integration กับ CI/CD
  • แก้ไขปัญหาที่พบบ่อย

ข้อดีของ Multi-Platform Builds:

  • รองรับ Apple Silicon M1/M2/M3
  • ลด cost ด้วย ARM instances
  • Image เดียวใช้ได้ทุกที่
  • Future-proof สำหรับ ARM adoption