Tüm eğitimler
TEKNİK REHBER GÖMÜLÜ LİNUX DOCKER 2026

Docker & Containers
Embedded Build Ortamı

tekrarlanabilir cross-compile ortamı, multi-arch image üretimi ve deterministik Yocto/Buildroot build'leri için container teknolojisi.

00 Container nedir

Container, Linux çekirdeğinin namespace ve cgroup mekanizmalarını kullanarak birbirinden izole edilmiş, hafif sanal ortamlardır.

Temel Linux mekanizmaları

Docker'ın altında üç temel kernel özelliği yatar. Namespace'ler her container'a ayrı PID, network, mount, UTS, IPC ve user namespace görünümü verir — container kendi dünyasında çalışıyor zanneder. Cgroup'lar (Control Groups) CPU, bellek, I/O ve ağ bant genişliği gibi kaynakların container başına sınırlandırılmasını sağlar. OverlayFS ise katmanlı bir dosya sistemi oluşturur: her image katmanı read-only olarak birikir, container yazma işlemi yalnızca en üst yazılabilir katmana yönlenir.

Dockerfile → image katmanları (OverlayFS) → container (namespace + cgroup izolasyonu) → process

VM vs Container karşılaştırması

ÖzellikSanal Makine (VM)Container
Başlangıç süresi30 saniye – 2 dakika100 ms – 1 saniye
OverheadYüksek — hypervisor + guest OSDüşük — kernel paylaşılır
BoyutGB mertebesinde diskMB – birkaç yüz MB
İzolasyonGüçlü — ayrı kernelOrta — namespace izolasyonu
TaşınabilirlikBüyük image, yavaş aktarımKatmanlı, registry üzerinden hızlı
Mimari emülasyonuQEMU gibi tam emülatör gerekirbuildx + QEMU user-static ile multi-arch
Donanım erişimiVirtIO, USB passthrough--device, --privileged ile sınırlı
Üretim kullanımıTam OS izolasyonu gereken senaryolarMicroservice, CI/CD, build ortamı

Embedded geliştirici için değeri

Tekrarlanabilir buildHost OS bağımsız — Ubuntu 20.04, 22.04, Debian veya Arch'ta aynı container aynı sonucu üretir
Toolchain yönetimiarm-linux-gnueabihf-gcc, aarch64-linux-gnu-gcc farklı sürümleri çakışma olmadan yan yana kullanılır
Multi-archbuildx ile tek komutla ARM32, ARM64, RISC-V image'ları aynı anda üretilir
CI tutarlılığıGeliştiricinin lokal ortamı = CI ortamı = aynı container image
Yocto / BuildrootGereken host bağımlılıkları container'da izole edilir; host sistemi kirlenmez

Bu bölümde

  • Container = namespace (izolasyon) + cgroup (kaynak kısıtlama) + OverlayFS (katmanlı FS)
  • VM: güçlü izolasyon, ağır; Container: hafif, hızlı, taşınabilir
  • Embedded için: tekrarlanabilir cross-compile ortamı, multi-arch image, CI tutarlılığı

01 Docker temelleri

Docker'ın temel komutları — image yönetimi, container çalıştırma, inceleme ve temizlik.

Kurulum

bash — Docker Engine kurulumu (Ubuntu)
# Resmi Docker repository ekle
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) \
  signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin

# Sudo olmadan Docker kullan
sudo usermod -aG docker $(whoami)
# Çıkış yap ve tekrar giriş yap

Image yönetimi

bash — image komutları
# Image indir
docker pull ubuntu:22.04
docker pull debian:12-slim

# Yerel image listesi
docker images
# REPOSITORY   TAG        IMAGE ID       CREATED        SIZE
# ubuntu       22.04      a6be0dcb2575   3 weeks ago    77.8MB
# debian       12-slim    c5e5c75af97e   3 weeks ago    74.8MB

# Image bilgisi
docker inspect ubuntu:22.04

# Image sil
docker rmi ubuntu:22.04

# Kullanılmayan image'ları temizle
docker image prune -a

Container çalıştırma

bash — docker run
# Tek seferlik container (çıkışta silinir)
docker run --rm ubuntu:22.04 uname -a

# İnteraktif bash shell
docker run --rm -it ubuntu:22.04 bash

# Arka planda çalıştır (daemon)
docker run -d --name my-server nginx:alpine
# d7a3f1b09e2c8f6...

# Çalışan container listesi
docker ps

# Tüm container'lar (durmuş dahil)
docker ps -a

# Çalışan container'a komut gönder
docker exec -it my-server sh

# Container durdur / başlat / sil
docker stop my-server
docker start my-server
docker rm my-server

# Container logları
docker logs -f my-server

Katman sistemi

Her Docker image, değişmez (immutable) OverlayFS katmanlarının birikimidir. FROM ubuntu:22.04 temel katmanı getirir; her RUN komutu yeni bir katman ekler. Container çalışırken en üste yazılabilir (writable) ince bir katman eklenir. Container silindiğinde bu katman da silinir — kalıcı veri için volume kullanılmalıdır.

bash — katman inceleme
# Image katmanlarını görüntüle
docker history ubuntu:22.04
# IMAGE          CREATED        CREATED BY                                      SIZE
# a6be0dcb2575   3 weeks ago    /bin/sh -c #(nop)  CMD ["bash"]                 0B
# <missing>      3 weeks ago    /bin/sh -c #(nop) ADD file:...                  77.8MB

# Katman ID'lerini ve boyutları detaylı görüntüle
docker inspect ubuntu:22.04 --format '{{range .RootFS.Layers}}{{println .}}{{end}}'

Bu bölümde

  • docker pull, docker images, docker rmi: image yaşam döngüsü
  • docker run --rm -it ubuntu:22.04 bash: tek seferlik interaktif container
  • docker exec -it: çalışan container'a bağlan
  • OverlayFS katmanları: immutable base + yazılabilir container katmanı

02 Dockerfile yazımı

Dockerfile direktifleri, katman optimizasyonu ve multi-stage build ile küçük üretim image'ı oluşturma.

Temel direktifler

DirektifAçıklamaÖrnek
FROMTemel imageFROM ubuntu:22.04
RUNKomut çalıştır (yeni katman)RUN apt-get install -y gcc
COPYHost → container dosya kopyalaCOPY src/ /app/src/
ADDCOPY + URL + tar açmaADD https://... /tmp/
ENVOrtam değişkeni tanımlaENV CROSS=aarch64-linux-gnu-
WORKDIRÇalışma dizini ayarlaWORKDIR /build
ARGBuild-time değişkenARG GCC_VERSION=13
CMDVarsayılan komut (override edilebilir)CMD ["/bin/bash"]
ENTRYPOINTSabit komut (CMD argüman olur)ENTRYPOINT ["make"]
EXPOSEPort bildirgesi (belgesel)EXPOSE 8080
USERÇalışma kullanıcısıUSER builder
VOLUMEMount noktası bildirgesiVOLUME ["/data"]

İyi bir Dockerfile örneği

Dockerfile — cross-compile builder
# syntax=docker/dockerfile:1
FROM ubuntu:22.04 AS base

# Build arg — toolchain prefix değiştirilebilir
ARG DEBIAN_FRONTEND=noninteractive
ARG CROSS_ARCH=aarch64

# Katman birleştirme: tek RUN = tek katman
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc-${CROSS_ARCH}-linux-gnu \
    g++-${CROSS_ARCH}-linux-gnu \
    make cmake ninja-build \
    pkg-config ca-certificates \
    git curl wget file \
  && rm -rf /var/lib/apt/lists/*

# Ortam değişkenleri
ENV CROSS_COMPILE=${CROSS_ARCH}-linux-gnu-
ENV ARCH=arm64
ENV PKG_CONFIG_PATH=/usr/${CROSS_ARCH}-linux-gnu/lib/pkgconfig

WORKDIR /build

# Root olmayan kullanıcı (güvenlik)
RUN useradd -m -u 1000 builder
USER builder

CMD ["/bin/bash"]

Multi-stage build

Multi-stage build, büyük build araçlarını içeren bir "builder" stage'i ile yalnızca üretilen binary'yi içeren küçük bir "runtime" stage'ini ayırır. Sonuç image'ı yalnızca çalıştırmak için gerekenleri taşır.

Dockerfile — multi-stage: build + minimal runtime
# ── Stage 1: Builder ──────────────────────────────────
FROM ubuntu:22.04 AS builder

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc-aarch64-linux-gnu make libssl-dev \
  && rm -rf /var/lib/apt/lists/*

WORKDIR /src
COPY . .

# Statik binary derle
RUN aarch64-linux-gnu-gcc \
    -static -O2 \
    -o /out/app \
    main.c \
  && aarch64-linux-gnu-strip /out/app

# ── Stage 2: Runtime (scratch — yalnızca binary) ──────
FROM scratch AS runtime

COPY --from=builder /out/app /app

ENTRYPOINT ["/app"]

# Build: docker build --target runtime -t my-app:arm64 .
# Sonuç image boyutu: yalnızca binary kadar (~500 KB)

Image build ve etiketleme

bash — docker build
# Temel build
docker build -t my-builder:latest .

# Build arg ile
docker build \
  --build-arg CROSS_ARCH=arm \
  -t my-builder:arm32 .

# Belirli stage'e kadar build
docker build --target builder -t my-builder:full .

# Build cache'i atla
docker build --no-cache -t my-builder:fresh .

# BuildKit ile paralel build (önerilir)
DOCKER_BUILDKIT=1 docker build -t my-builder:latest .
NOT

Dockerfile'da RUN komutlarını && ile birleştirmek ve sonuna rm -rf /var/lib/apt/lists/* eklemek katman sayısını ve image boyutunu önemli ölçüde azaltır. Her ayrı RUN satırı yeni bir OverlayFS katmanı oluşturur ve bu katmanlar silinmiş dosyaları bile kapasiteye sayar.

Bu bölümde

  • Temel direktifler: FROM, RUN, COPY, ENV, WORKDIR, ARG, CMD, ENTRYPOINT
  • RUN komutlarını birleştir + rm -rf /var/lib/apt/lists/*: küçük katman
  • Multi-stage build: builder stage → runtime stage (scratch) — minimal image
  • docker build --build-arg CROSS_ARCH=arm -t my-builder:arm32 .: parametrik build

03 Volume ve bind mount

Container dışında kalıcı veri tutma yöntemleri — named volume, bind mount ve tmpfs arasındaki farklar.

Bind mount

Host dosya sisteminin belirli bir dizini container içine monte edilir. Kaynak kodu geliştirme ve build ortamları için idealdir: host'ta değiştirilen dosyalar anında container içinde görünür.

bash — bind mount kullanımı
# -v /host/path:/container/path
# Mevcut dizini /build olarak monte et
docker run --rm -it \
  -v "$(pwd):/build" \
  my-builder:latest \
  make -C /build -j$(nproc)

# Read-only mount (kaynak kod değiştirilmesin)
docker run --rm \
  -v "$(pwd)/src:/build/src:ro" \
  -v "$(pwd)/output:/build/output" \
  my-builder:latest \
  make -C /build

# Yeni sözdizimi (--mount)
docker run --rm \
  --mount "type=bind,source=$(pwd),target=/build" \
  my-builder:latest bash

Named volume

Docker tarafından yönetilen kalıcı veri depolama. Container silinse bile volume verisi korunur. sstate-cache ve dl/ dizinleri gibi build artifact'leri için idealdir.

bash — named volume
# Volume oluştur
docker volume create yocto-sstate
docker volume create buildroot-dl

# Volume listesi
docker volume ls

# Volume ile container çalıştır
docker run --rm \
  -v yocto-sstate:/build/sstate-cache \
  -v buildroot-dl:/build/dl \
  -v "$(pwd):/build/src:ro" \
  yocto-builder:latest \
  bitbake core-image-minimal

# Volume bilgisi
docker volume inspect yocto-sstate
# "Mountpoint": "/var/lib/docker/volumes/yocto-sstate/_data"

# Volume sil
docker volume rm yocto-sstate

# Kullanılmayan volume'ları temizle
docker volume prune

Bind mount vs Named volume karşılaştırması

ÖzellikBind MountNamed Volume
Host konumuKullanıcı tarafından belirlenirDocker tarafından yönetilir (/var/lib/docker/volumes/)
TaşınabilirlikHost yola bağımlıTaşınabilir — isimle referans
PerformansLinux'ta yüksek; macOS'ta düşükLinux'ta yüksek
YedeklemeNormal dosya yedeklemedocker run --rm -v vol:/data ubuntu tar czf - /data
KullanımKaynak kod, konfigürasyonBuild cache, veritabanı verisi

tmpfs mount

bash — tmpfs (bellekte geçici dosya sistemi)
# /tmp ve /run gibi geçici dizinler için ideal
# Container silindiğinde veri kaybolur
docker run --rm \
  --tmpfs /tmp:rw,size=512m,mode=1777 \
  my-builder:latest bash

# --mount sözdizimi ile
docker run --rm \
  --mount "type=tmpfs,target=/tmp,tmpfs-size=512m" \
  my-builder:latest bash

Bu bölümde

  • Bind mount (-v $(pwd):/build): kaynak kodu için — host değişikliği anında yansır
  • Named volume (docker volume create): build cache, sstate, dl/ için — container'dan bağımsız kalıcı veri
  • tmpfs (--tmpfs /tmp): geçici, bellekte — I/O yoğun işlemler için hızlı
  • :ro son eki: read-only mount — kaynak korunur

04

Docker ağ modları — bridge, host, none; custom network oluşturma ve container-to-container iletişim.

Ağ sürücüleri

SürücüAçıklamaKullanım
bridgeVarsayılan — docker0 köprüsü üzerinde NATBağımsız container'lar, port publish
hostHost ağ stack'ini paylaş — izolasyon yokPerformans kritik, ağ araçları testi
noneAğ arayüzü yok — tamamen izoleAğ erişimi gerektirmeyen build işlemleri
overlaySwarm multi-host ağıDocker Swarm cluster
macvlanContainer'a doğrudan MAC adresi ataLegacy uygulamalar, L2 ağ erişimi

Port publish ve bridge ağı

bash — port publish
# Host port 8080 → container port 80
docker run -d -p 8080:80 nginx:alpine

# Belirli interface'e bind
docker run -d -p 127.0.0.1:8080:80 nginx:alpine

# Tüm EXPOSE edilen portları rastgele yayınla
docker run -d -P nginx:alpine

# Çalışan port mappingleri görüntüle
docker port my-container

# Host ağını paylaş (Linux only)
docker run --rm --network host nginx:alpine

Custom network ve container-to-container iletişim

bash — custom bridge network
# Custom bridge network oluştur
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --ip-range 172.20.240.0/20 \
  build-net

# Container'ları aynı ağa bağla
docker run -d --name registry \
  --network build-net \
  registry:2

docker run --rm --network build-net \
  my-builder:latest \
  curl http://registry:5000/v2/_catalog

# Aynı custom network'teki container'lar
# birbirlerine isimle (DNS) erişebilir

# Network listesi
docker network ls

# Network bilgisi
docker network inspect build-net

# Temizlik
docker network rm build-net

Bu bölümde

  • Bridge (varsayılan): NAT + port publish; host: izolasyon yok, maksimum performans
  • -p 8080:80: host 8080 → container 80; -P: tüm EXPOSE portları otomatik publish
  • Custom bridge network: aynı ağdaki container'lar DNS ile birbirini bulur
  • Build ortamları için: --network none — ağ erişimi gerektirmeyen deterministik build

05 Multi-arch build

Docker buildx ile ARM32, ARM64, RISC-V image'larını tek komutla üretme — embedded geliştirme için kritik özellik.

Neden multi-arch?

Embedded sistemlerde çalışacak container image'ları hedef mimari için derlenmiş binary içermelidir. docker buildx, QEMU user-static ve binfmt_misc kullanarak x86-64 host üzerinde farklı mimariler için image üretir ve aynı tag'e birden fazla mimariyi paketler (manifest list).

buildx ve QEMU kurulumu

bash — buildx kurulumu
# Docker Buildx eklentisi (modern Docker'da dahili gelir)
docker buildx version
# github.com/docker/buildx v0.13.1 ...

# QEMU user-static kur (farklı mimari binary çalıştırma için)
sudo apt-get install -y qemu-user-static binfmt-support

# binfmt_misc kayıt (QEMU user-static ile otomatik)
docker run --rm --privileged \
  multiarch/qemu-user-static --reset -p yes

# Binfmt kayıtlarını doğrula
ls /proc/sys/fs/binfmt_misc/ | grep qemu
# qemu-aarch64
# qemu-arm
# qemu-riscv64
# ...

# Multi-arch builder oluştur
docker buildx create \
  --name multiarch-builder \
  --driver docker-container \
  --use

# Builder'ı başlat ve mimarileri doğrula
docker buildx inspect --bootstrap
# Platforms: linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6, linux/riscv64

Multi-arch image build ve push

bash — multi-platform build
# ARM64 + ARM32v7 için image oluştur ve registry'e push et
docker buildx build \
  --platform linux/arm64,linux/arm/v7 \
  -t ghcr.io/myorg/my-app:latest \
  --push \
  .

# Geniş platform listesi (amd64 dahil)
docker buildx build \
  --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 \
  -t ghcr.io/myorg/my-app:1.0.0 \
  -t ghcr.io/myorg/my-app:latest \
  --push .

# Push etmeden yerel test (belirli platform)
docker buildx build \
  --platform linux/arm64 \
  --output "type=docker,name=my-app:arm64-test" \
  --load \
  .

# Manifest list incele
docker buildx imagetools inspect ghcr.io/myorg/my-app:latest

Multi-arch Dockerfile — TARGETARCH ile platform tespiti

Dockerfile — TARGETARCH kullanımı
# syntax=docker/dockerfile:1
FROM ubuntu:22.04

# Buildx tarafından otomatik doldurulur
ARG TARGETARCH
ARG TARGETVARIANT

RUN apt-get update && apt-get install -y --no-install-recommends \
    curl ca-certificates \
  && rm -rf /var/lib/apt/lists/*

# Mimariye göre farklı binary indir
RUN case "${TARGETARCH}${TARGETVARIANT}" in \
      "arm64")   ARCH_SLUG="aarch64"  ;; \
      "armv7")   ARCH_SLUG="armv7l"   ;; \
      "amd64")   ARCH_SLUG="x86_64"   ;; \
      *)         echo "Unsupported: ${TARGETARCH}"; exit 1 ;; \
    esac \
  && curl -Lo /usr/local/bin/my-tool \
      "https://example.com/releases/${ARCH_SLUG}/my-tool" \
  && chmod +x /usr/local/bin/my-tool

ENTRYPOINT ["/usr/local/bin/my-tool"]
UYARI

QEMU user-static ile ARM binary çalıştırma, native x86-64'e göre 5–10x yavaştır. Multi-arch Dockerfile'da C derleme gerektiren RUN adımları için cross-compilation tercih edin: RUN apt-get install -y gcc-aarch64-linux-gnu && aarch64-linux-gnu-gcc -O2 -o app main.c. Bu yaklaşım hem daha hızlıdır hem de QEMU bağımlılığını ortadan kaldırır.

Bu bölümde

  • docker buildx create --use: multi-arch builder etkinleştir
  • multiarch/qemu-user-static --reset -p yes: binfmt_misc ile ARM binary çalıştırma
  • --platform linux/arm64,linux/arm/v7: tek build komutuyla çift mimari
  • TARGETARCH değişkeni: Dockerfile içinde hedef mimariyi algıla

06 Embedded build environment

Cross-toolchain içeren Docker image oluşturma ve kaynak kodu bind mount ile container içinde derleme — tekrarlanabilir embedded build ortamı.

Cross-toolchain Dockerfile

Dockerfile.arm-builder — ARM32 + ARM64 toolchain
# syntax=docker/dockerfile:1
FROM ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y --no-install-recommends \
    # ARM 32-bit hard-float toolchain
    gcc-arm-linux-gnueabihf \
    g++-arm-linux-gnueabihf \
    # ARM 64-bit toolchain
    gcc-aarch64-linux-gnu \
    g++-aarch64-linux-gnu \
    # Build araçları
    make cmake ninja-build \
    autoconf automake libtool \
    pkg-config bc flex bison \
    # Kernel araçları
    libssl-dev libncurses-dev \
    # Genel yardımcılar
    git wget curl file xz-utils \
    ca-certificates python3 python3-pip \
  && rm -rf /var/lib/apt/lists/*

# ARM32 ve ARM64 için symlink'ler
ENV CC_ARM32=arm-linux-gnueabihf-gcc
ENV CXX_ARM32=arm-linux-gnueabihf-g++
ENV CC_ARM64=aarch64-linux-gnu-gcc
ENV CXX_ARM64=aarch64-linux-gnu-g++

WORKDIR /build

# Root olmayan kullanıcı — host UID ile eşleştir
ARG UID=1000
ARG GID=1000
RUN groupadd -g ${GID} builder \
  && useradd -m -u ${UID} -g builder builder

USER builder
CMD ["/bin/bash"]

Build ve kullanım

bash — builder image kullanımı
# Image oluştur (host UID geçirerek — dosya izinleri için)
docker build \
  --build-arg UID=$(id -u) \
  --build-arg GID=$(id -g) \
  -f Dockerfile.arm-builder \
  -t arm-builder:latest .

# Kaynak kodu bind mount ile ARM64 derle
docker run --rm \
  -v "$(pwd):/build" \
  arm-builder:latest \
  aarch64-linux-gnu-gcc -O2 -o /build/app_arm64 /build/src/main.c

# Makefile projesi için
docker run --rm \
  -v "$(pwd):/build" \
  arm-builder:latest \
  make -C /build \
    CROSS_COMPILE=aarch64-linux-gnu- \
    ARCH=arm64 \
    -j$(nproc)

# CMake projesi için
docker run --rm \
  -v "$(pwd):/build" \
  arm-builder:latest \
  bash -c "cmake -B /build/build-arm64 \
    -DCMAKE_TOOLCHAIN_FILE=/build/cmake/arm64-toolchain.cmake \
    -DCMAKE_BUILD_TYPE=Release /build \
  && cmake --build /build/build-arm64 -j$(nproc)"

# Derlenen binary'nin mimarisini doğrula
file app_arm64
# app_arm64: ELF 64-bit LSB pie executable, ARM aarch64, ...

CMake toolchain dosyası

cmake/arm64-toolchain.cmake
# CMake cross-compilation toolchain — AArch64
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(CROSS_PREFIX aarch64-linux-gnu-)

set(CMAKE_C_COMPILER   ${CROSS_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${CROSS_PREFIX}g++)
set(CMAKE_AR           ${CROSS_PREFIX}ar)
set(CMAKE_STRIP        ${CROSS_PREFIX}strip)

set(CMAKE_FIND_ROOT_PATH  /usr/aarch64-linux-gnu)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# Cortex-A53 optimizasyonu
set(CMAKE_C_FLAGS   "-mcpu=cortex-a53 -O2")
set(CMAKE_CXX_FLAGS "-mcpu=cortex-a53 -O2")

Bu bölümde

  • ARM32 + ARM64 cross-toolchain tek Dockerfile'da — gcc-arm-linux-gnueabihf + gcc-aarch64-linux-gnu
  • --build-arg UID=$(id -u): container içindeki dosya izinleri host kullanıcısıyla eşleşir
  • Bind mount + aarch64-linux-gnu-gcc: host dizinini container içinde derle, sonuç host'ta
  • CMake toolchain dosyası: cross-compile için sysroot ve prefix tanımı

07 Docker Compose

Çok servisli ortamları YAML ile tanımlama — build sunucusu, registry, sstate cache servisi gibi embedded geliştirme altyapısının Compose ile yönetimi.

docker-compose.yml yapısı

docker-compose.yml — embedded build stack
services:

  # ── Cross-compile builder ──────────────────────────
  builder:
    build:
      context: .
      dockerfile: Dockerfile.arm-builder
      args:
        UID: "${UID:-1000}"
        GID: "${GID:-1000}"
    volumes:
      - "./src:/build/src:ro"
      - "./output:/build/output"
      - buildroot-dl:/build/dl
    environment:
      - CROSS_COMPILE=aarch64-linux-gnu-
      - ARCH=arm64
    working_dir: /build
    command: make -j4

  # ── Özel Docker registry ──────────────────────────
  registry:
    image: registry:2
    ports:
      - "5000:5000"
    volumes:
      - registry-data:/var/lib/registry
    environment:
      REGISTRY_STORAGE_DELETE_ENABLED: "true"
    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://localhost:5000/v2/"]
      interval: 10s
      timeout: 5s
      retries: 3

  # ── Build artifact sunucusu ────────────────────────
  artifact-server:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - "./output:/usr/share/nginx/html:ro"
    depends_on:
      builder:
        condition: service_completed_successfully

volumes:
  buildroot-dl:
  registry-data:

Compose komutları

bash — docker compose
# Tüm servisleri başlat
docker compose up -d

# Build ve başlat (image yeniden oluştur)
docker compose up --build -d

# Yalnızca builder servisini çalıştır (tek seferlik)
docker compose run --rm builder

# Servis logları
docker compose logs -f builder

# Servis durumu
docker compose ps

# Tüm servisleri durdur
docker compose down

# Volume'larla birlikte temizle
docker compose down -v

Health check ile depends_on

docker-compose.yml — sağlık kontrolü
services:
  sstate-server:
    image: nginx:alpine
    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://localhost/"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

  yocto-builder:
    build: .
    depends_on:
      sstate-server:
        condition: service_healthy
    environment:
      - SSTATE_MIRROR=http://sstate-server/sstate-cache

Bu bölümde

  • docker-compose.yml: servisleri, volume'ları ve bağımlılıkları tek dosyada tanımla
  • depends_on: condition: service_healthy: servis sağlıklı olana kadar bekle
  • docker compose run --rm builder: tek seferlik build komutu çalıştırma
  • Named volume'lar Compose dışında da kalıcıdır — birden fazla Compose dosyası paylaşabilir

08 Registry

Docker Hub, GitHub Container Registry ve özel registry kullanımı — embedded build image'larını ekiple paylaşma.

Docker Hub

bash — Docker Hub push/pull
# Oturum aç
docker login
# Username: myusername
# Password: ...
# Login Succeeded

# Image etiketle (Docker Hub formatı: kullanıcı/repo:tag)
docker tag arm-builder:latest myusername/arm-builder:latest
docker tag arm-builder:latest myusername/arm-builder:22.04-gcc13

# Push
docker push myusername/arm-builder:latest
docker push myusername/arm-builder:22.04-gcc13

# Pull
docker pull myusername/arm-builder:latest

GitHub Container Registry (ghcr.io)

bash — ghcr.io
# GitHub Personal Access Token ile oturum aç
# Token izinleri: read:packages, write:packages, delete:packages
echo "${GITHUB_TOKEN}" | docker login ghcr.io \
  -u myusername --password-stdin

# Image etiketle (ghcr.io/org/repo:tag)
docker tag arm-builder:latest \
  ghcr.io/myorg/arm-builder:latest

# Push
docker push ghcr.io/myorg/arm-builder:latest

# Multi-arch push buildx ile
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t ghcr.io/myorg/arm-builder:latest \
  --push .

# GitHub Actions'ta GITHUB_TOKEN ile otomatik login
# - uses: docker/login-action@v3
#   with:
#     registry: ghcr.io
#     username: ${{ github.actor }}
#     password: ${{ secrets.GITHUB_TOKEN }}

Özel (private) registry

bash — yerel registry kurulumu
# Registry container başlat
docker run -d \
  --name local-registry \
  --restart always \
  -p 5000:5000 \
  -v registry-data:/var/lib/registry \
  registry:2

# Image push
docker tag arm-builder:latest localhost:5000/arm-builder:latest
docker push localhost:5000/arm-builder:latest

# Image pull
docker pull localhost:5000/arm-builder:latest

# Registry catalog
curl http://localhost:5000/v2/_catalog
# {"repositories":["arm-builder"]}

# Tag listesi
curl http://localhost:5000/v2/arm-builder/tags/list
# {"name":"arm-builder","tags":["latest"]}
NOT

Özel registry TLS sertifikası olmadan çalıştığında Docker insecure registry olarak işaretlenmesini gerektirir. /etc/docker/daemon.json dosyasına {"insecure-registries": ["192.168.1.100:5000"]} ekleyin ve sudo systemctl restart docker ile yeniden başlatın. Üretim ortamlarında her zaman TLS kullanın.

Bu bölümde

  • Docker Hub: docker logindocker tagdocker push
  • ghcr.io: GITHUB_TOKEN ile login — GitHub Actions pipeline ile entegre
  • Özel registry: docker run registry:2 -p 5000:5000 — yerel ağda paylaşım
  • Multi-arch push: docker buildx build --platform ... --push — manifest list

09 Pratik: Yocto/Buildroot build container

Yocto Project gereksinimlerini içeren Docker image, sstate-cache volume mount ve CI'da deterministik build — ekip genelinde tekrarlanabilir embedded build ortamı.

Yocto builder Dockerfile

Dockerfile.yocto — Scarthgap (5.0 LTS) builder
# syntax=docker/dockerfile:1
FROM ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive

# Yocto Scarthgap resmi bağımlılıkları
RUN apt-get update && apt-get install -y --no-install-recommends \
    gawk wget git diffstat unzip texinfo gcc \
    build-essential chrpath socat cpio python3 \
    python3-pip python3-pexpect xz-utils debianutils \
    iputils-ping python3-git python3-jinja2 \
    python3-subunit zstd liblz4-tool file \
    libacl1 libegl1-mesa libsdl1.2-dev \
    pylint xterm \
  && rm -rf /var/lib/apt/lists/*

# repo tool (Android repo)
RUN curl -o /usr/local/bin/repo \
    https://storage.googleapis.com/git-repo-downloads/repo \
  && chmod a+x /usr/local/bin/repo

# Host UID ile eşleşen kullanıcı
ARG UID=1000
ARG GID=1000
RUN groupadd -g ${GID} yocto \
  && useradd -m -u ${UID} -g yocto -s /bin/bash yocto \
  && echo "yocto ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers

# Git config (BitBake için gerekli)
RUN git config --system user.email "ci@build.local" \
  && git config --system user.name "Yocto CI"

USER yocto
WORKDIR /build

CMD ["/bin/bash"]

Build scripti ve volume yapısı

bash — Yocto container build
# Image oluştur
docker build \
  --build-arg UID=$(id -u) \
  --build-arg GID=$(id -g) \
  -f Dockerfile.yocto \
  -t yocto-builder:scarthgap .

# Kalıcı volume'lar oluştur
docker volume create yocto-sstate    # sstate-cache (~20–50 GB)
docker volume create yocto-downloads # indirilen kaynaklar (~5–10 GB)

# Yocto build çalıştır
docker run --rm -it \
  -v "$(pwd)/poky:/build/poky:ro" \
  -v "$(pwd)/meta-custom:/build/meta-custom:ro" \
  -v yocto-sstate:/build/build/sstate-cache \
  -v yocto-downloads:/build/build/downloads \
  -v "$(pwd)/output:/build/output" \
  yocto-builder:scarthgap \
  bash -c "
    source /build/poky/oe-init-build-env /build/build
    bitbake core-image-minimal 2>&1 | tee /build/output/build.log
  "

local.conf container yapılandırması

build/conf/local.conf — container içi ayarlar
# Makine tanımı
MACHINE = "qemuarm64"

# Paralel build (container CPU sayısına göre)
BB_NUMBER_THREADS = "4"
PARALLEL_MAKE = "-j 4"

# sstate-cache dizini (volume mount noktası)
SSTATE_DIR = "/build/build/sstate-cache"

# Downloads dizini (volume mount noktası)
DL_DIR = "/build/build/downloads"

# CI modunda interaktif sorulardan kaçın
CONNECTIVITY_CHECK_URIS = ""

# Disk alanı uyarı eşiği
BB_DISKMON_DIRS = "\
  STOPTASKS,/build,1G,100K \
  ABORT,/build,100M,1K"

GitHub Actions CI entegrasyonu

.github/workflows/yocto-build.yml
name: Yocto Build CI

on:
  push:
    paths: ['meta-custom/**']

jobs:
  yocto-build:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive

      - name: Cache sstate (GitHub Actions cache)
        uses: actions/cache@v4
        with:
          path: sstate-cache
          key: yocto-sstate-${{ hashFiles('meta-custom/**/*.bb') }}
          restore-keys: yocto-sstate-

      - name: Build Yocto image
        run: |
          docker build \
            --build-arg UID=$(id -u) \
            --build-arg GID=$(id -g) \
            -f Dockerfile.yocto \
            -t yocto-builder:ci .

          docker run --rm \
            -v "$(pwd):/build/workspace:ro" \
            -v "$(pwd)/sstate-cache:/build/build/sstate-cache" \
            -v "$(pwd)/artifacts:/build/output" \
            yocto-builder:ci \
            bash -c "
              source /build/workspace/poky/oe-init-build-env /build/build
              cp /build/workspace/conf/local.conf conf/local.conf
              bitbake core-image-minimal
              cp tmp/deploy/images/qemuarm64/* /build/output/
            "

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: yocto-images
          path: artifacts/
NOT

Yocto ilk build büyük bir sstate-cache oluşturur (20–50 GB). GitHub Actions'ın ücretsiz katmanında 10 GB cache sınırı bulunur. Büyük sstate cache için self-hosted runner veya sstate-cache'i ayrı bir artifact sunucusunda barındırmak daha verimlidir. SSTATE_MIRRORS değişkeniyle harici sstate mirror tanımlanabilir.

Bu bölümde

  • Yocto Scarthgap için tüm bağımlılıkları içeren Dockerfile — resmi bağımlılık listesi
  • sstate-cache ve downloads için named volume — build'ler arası paylaşım, hız
  • GitHub Actions: actions/cache ile sstate-cache persist etme
  • --build-arg UID=$(id -u): dosya izin sorunu olmadan host dizinine yazma