Giriş
Apple Silicon (ARM64), Raspberry Pi gibi cihazlarla birlikte “aynı imajı farklı mimarilerde çalıştırma” ihtiyacı günlük hayatın bir parçası oldu. Docker Buildx, tek bir komutla linux/amd64 ve linux/arm64 için çok mimarili (multi-arch) imajlar üretmenizi sağlıyor. Bu rehberde, yerelde Buildx ile derleme, doğru Dockerfile pratikleri, imajı Docker Hub’a itme ve son olarak GitHub Actions ile otomatik yayımlamayı adım adım anlatıyorum.
Önkoşullar
- Docker 24+ veya Docker Desktop (BuildKit varsayılan açık olmalı)
- Docker Hub veya GHCR hesabı (örneklerde Docker Hub kullanacağım)
- GitHub deposu (Actions için)
Buildx Kurulumu ve Kontrolü
Güncel Docker Desktop, buildx ve QEMU emülasyonu ile birlikte gelir. Terminalde aşağıdaki komutlarla Buildx’in aktif olduğunu kontrol edin:
docker buildx version
docker buildx ls
Gerekirse yeni bir builder oluşturabilirsiniz:
docker buildx create --name multiarch --use
docker buildx inspect --bootstrap
“qemu not registered” gibi bir hata alırsanız, Docker Desktop’ı güncelleyin veya Linux için QEMU’yu kurun. Çoğu yeni kurulumda ekstra adım gerekmeyecektir.
Örnek Dockerfile (Go ile statik ikili)
Dil bağımsız olarak çalışabilirsiniz; ancak Go ile statik ikili üretmek multi-arch derlemelerde idealdir. Minimal ve güvenli bir imaj için distroless veya scratch tabanını tercih edin.
# Dockerfile
# 1) Build aşaması
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# CGO kapalı, statik derleme
RUN CGO_ENABLED=0 GOOS=linux GOARCH=$(go env GOARCH) go build -ldflags="-s -w" -o app ./cmd/server
# 2) Minimal çalışma aşaması
FROM gcr.io/distroless/static:nonroot
WORKDIR /app
COPY --from=builder /src/app /app/app
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/app/app"]
Not: Go projesinde “./cmd/server” yolu örnektir. Projenize göre düzenleyin. Go dışındaki dillerde (Node.js, Python) multi-stage ve mimariye uygun resmi taban imajları kullanın. .dockerignore dosyasıyla gereksiz dosyaları dışarıda bırakmayı unutmayın.
Yerelde Çok Mimarili İmaj Derleme ve İtme
Önce Docker Hub’a giriş yapın:
docker login
Ardından Buildx ile iki mimariye birden derleyip tek bir çoklu manifest altında toplayın ve push edin:
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t KULLANICI_ADI/uygulama:1.0.0 \
-t KULLANICI_ADI/uygulama:latest \
--provenance=true --sbom=true \
--push .
Manifest’i doğrulamak için:
docker buildx imagetools inspect KULLANICI_ADI/uygulama:latest
GitHub Actions ile Otomatik Yayınlama
Her push veya tag ile otomatik imaj üretmek için .github/workflows/docker.yml adında bir iş akışı oluşturun. Aşağıdaki örnek, semantik sürüm etiketlerini otomatik algılar ve iki mimariye birden push eder. Docker Hub kullanıcı adı ve erişim token’ınızı repo Secrets kısmında DOCKERHUB_USERNAME ve DOCKERHUB_TOKEN olarak saklayın.
name: Docker Multi-Arch
on:
push:
branches: [ "main" ]
tags: [ "v*" ]
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Checkout
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: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ secrets.DOCKERHUB_USERNAME }}/uygulama
tags: |
type=ref,event=branch
type=ref,event=tag
type=sha
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: true
sbom: true
Bu akışta setup-qemu-action emülasyon için, build-push-action ise derleme ve push için kullanılır. metadata-action, tag yönetimini kolaylaştırır; main branch için “latest” benzeri etiketler ve tag push için semantik sürümler üretir.
OCI Etiketleri, Güvenlik ve İpuçları
- OCI etiketleri (org.opencontainers.image.*) ile kaynak kod, lisans ve açıklama bilgilerini ekleyin. metadata-action bunu otomatik sağlar.
- sbom: true ve provenance: true ile tedarik zinciri görünürlüğünü artırın.
- .dockerignore ile node_modules, build çıktıları, test verileri gibi gereksiz klasörleri dışarıda tutun; imaj boyutu ve gizlilik açısından önemlidir.
- Çok aşamalı (multi-stage) Dockerfile ile sadece gereken dosyaları çalışma imajına kopyalayın.
- Bazı dil ekosistemlerinde mimariye özgü bağımlılıklar olabilir. Özellikle Python’da native modüller içeren paketlerde uygun taban imajını ve derleme araçlarını kullanın.
Yaygın Hatalar ve Çözümleri
- Hata: “no match for platform in manifest” — Kullandığınız baz imaj ilgili mimariyi desteklemiyor. Aynı imajın çok mimarili varyantını (ör. alpine, debian-slim) tercih edin.
- Hata: “exec format error” — Yanlış mimari için derlenmiş ikiliyi çalıştırıyorsunuz. Multi-stage içinde hedef GOARCH/GOOS (veya eşdeğerleri) doğru ayarlanmalı.
- Hata: “qemu not registered” — QEMU emülasyonu kurulu değil. GitHub Actions’ta setup-qemu-action kullanın; yerelde Docker Desktop güncel olsun.
- Hata: “denied: requested access to the resource is denied” — Registry girişiniz veya tag adı hatalı. docker login ve depo adını doğrulayın.
Sonuç
Buildx sayesinde tek bir komutla amd64 ve arm64 için üretim yapabilir, tek bir etiket altında birleştirip dağıtabilirsiniz. GitHub Actions ile bunu CI/CD’ye bağladığınızda yeni sürümleriniz saniyeler içinde Docker Hub’a düşer. Doğru baz imaj, temiz Dockerfile ve önbellekleme stratejileri ile hem derleme sürenizi hem de imaj boyutlarınızı önemli ölçüde iyileştirebilirsiniz.