📌 Hızlı Özet & Temel Çıkarım:
Edge tarafta (Jetson Orin / NX, sahadaki mini PC) Docker kullanıyorsanız hedef “Kubernetes textbook” değil; öngörülebilir imaj, root’suz süreç, kontrollü volume ve ölçülü NVIDIA runtimedır. Bu yazı, pusula / laboratuvar deploy’larında işime yarayan sıkılaştırma ve boyut küçültme adımlarını anlatıyor — enterprise distroless fetişizmi olmadan.
Edge’de container neden ayrı bir problem?
Bulut VM’de yanlış Dockerfile can sıkar. Jetson’da yanlış Dockerfile:
- eMMC / NVMe’yi şişirir (katman cache + eski imajlar),
- GPU erişimi için
--privilegedalışkanlığı doğurur, aptile gelen debug araçları CVE listesini uzatır,- sahada SSH ile “bir kerelik root” debug’ı kalıcı hale getirir.
ROS 2 düğümlerini container’da çalıştıran takımlar için ek katman: host’taki /dev/ttyUSB*, kamera, GPU. İzolasyon ile donanım erişimi arasında bilinçli trade-off gerekir; “hepsini privileged yap” çözüm değildir.
Önce boyutu ölç, sonra kes
Kör optimizasyon yok. Mevcut imaj:
docker images --format '{{.Repository}}:{{.Tag}}\t{{.Size}}'
docker history --no-trunc your-registry/usv-bridge:latest
docker history hangi katmanın şişirdiğini gösterir: çoğu zaman apt-get install + unutulmuş build bağımlılıkları veya COPY . . ile gelen dataset/bag artıklarıdır.
.dockerignore (sık unutulur):
.git
**/__pycache__
**/*.bag
**/bags/
**/datasets/
**/node_modules
**/.venv
**/build
**/install
**/log
Tek bir 2 GB bag’in imaja girmesi, “Alpine’e geçelim” tartışmasından daha pahalıdır.
Multi-stage: derleme host’ta, runtime ince
Python ROS köprüsü / telemetri servisi örneği (x86 CI’da build, arm64 için buildx ile ayrı etiket):
# syntax=docker/dockerfile:1.6
FROM python:3.10-slim-bookworm AS builder
WORKDIR /build
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
FROM python:3.10-slim-bookworm AS runtime
RUN useradd --create-home --uid 10001 appuser \
&& apt-get update && apt-get install -y --no-install-recommends \
tini \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /install /usr/local
COPY --chown=appuser:appuser src/ ./src/
USER appuser
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["python", "-m", "src.bridge"]
Neden tini? PID 1 sinyal ve zombie reaping; edge’de container restart politikalarıyla birlikte daha az “zombie python” sürprizi.
CUDA / DeepStream iş yükünde base imaj NVIDIA’nın L4T / CUDA imajı olmak zorunda kalabilir. O durumda multi-stage hâlâ geçerli: derleme araçlarını final katmana taşımayın; sadece wheel / binary kopyalayın.
Non-root ve yetki daraltma
USER root ile sahaya çıkan imaj, container escape sonrası doğrudan host root’a giden yolu kısaltır. useradd yetmez; compose tarafında da kilitleyin:
# docker-compose.edge.yml
services:
bridge:
image: your-registry/usv-bridge:1.4.2
read_only: true
tmpfs:
- /tmp:size=64m
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
# Seri port gerekiyorsa bilinçli ekle:
# devices:
# - /dev/ttyUSB0:/dev/ttyUSB0
# group_add: ["dialout"]
environment:
MQTT_URL: ${MQTT_URL}
restart: unless-stopped
read_only: true + tmpfs /tmp, yazılabilir rootfs ihtiyacını keser. Uygulama log’u stdout’a gitsin; dosyaya yazmak zorundaysa ayrı yazılabilir volume mount edin, tüm FS’i açmayın.
GPU için NVIDIA Container Toolkit kullanın; --privileged yerine --gpus all (veya device id) tercih edin. Privileged, “bir kerelik çalıştı” ile kalıcı alışkanlık olur.
arm64 / Jetson build gerçekleri
Laptop’unuz amd64, Jetson arm64 ise:
docker buildx create --use --name edgebuilder
docker buildx build \
--platform linux/arm64 \
-t your-registry/usv-bridge:1.4.2 \
--push .
QEMU ile emülasyon yavaş ve bazen kırılgandır. Mümkünse CI’da arm64 runner veya Jetson üzerinde native build; sonra registry’ye push.
NVIDIA runtime imaj tag’lerini rastgele latest ile çekmeyin. L4T sürümü JetPack ile kilitlidir; yanlış base imaj “CUDA not found” geceleri üretir.
Secret ve config: imaja gömme
Klasik hata:
ENV AWS_SECRET_ACCESS_KEY=AKIA...
COPY id_rsa /root/.ssh/
Doğru yön:
- Compose / systemd EnvironmentFile
- Docker secrets (Swarm) veya host’ta root-only dosya + bind mount (
:ro) - Registry credential’ı CI secret’ında
volumes:
- /etc/usv/bridge.env:/run/secrets/bridge.env:ro
Uygulama başlarken dosyayı okusun; docker history içinde secret görünmesin.
Tarama: imaj üretilince Trivy
trivy image --severity HIGH,CRITICAL --exit-code 1 your-registry/usv-bridge:1.4.2
CI’da build sonrası aynı komut. Base imajı ayda bir yükseltin; slim bile eski kalırsa CVE birikir. “Minimal imaj” iddiası, taranmamış 2 yıllık Alpine ile çelişir.
Ne zaman container kullanmayayım?
- Tek bir C++ düğümü, systemd + venv ile yıllardır stabil → zorla Docker’lamayın.
- Sert gerçek zaman (hard RT) kontrol döngüsü → container jitter’ı ölçmeden production’a koymayın.
- Kernel modül / özel DPI kamera stack’i → önce host driver, sonra gerekirse ince wrapper.
Docker, edge’de dağıtım tutarlılığı için araçtır; her satır kodun evi olmak zorunda değil.
Sahada işletme checklist’i
docker system df— aylık; dangling imajları budayın.- Tag’ler semver;
:latestile otomatik pull kapalı. - Healthcheck veya dış watchdog (systemd
Restart=). - Log’lar JSON/stdout → journald veya promtail; container FS’e rotasyon yok.
- Güncelleme: yeni imaj pull → compose up → eski tag’i bir süre sakla (rollback).
Resource limit: komşu süreci ezdirme
Jetson’da aynı anda bridge container, rosbag kayıt ve bir sinir ağı inferansı koşuyorsa bellek yarışı gerçek bir arıza modudur. Compose’da limit koymak “enterprise overkill” değil, sahada panik önler:
services:
bridge:
mem_limit: 512m
cpus: 1.5
pids_limit: 256
Limit aşımında süreç ölür; bu acıtır ama tüm board’un OOM killer ile rastgele process öldürmesinden iyidir. Limit değerlerini tahminle değil, docker stats ve birkaç saatlik sahada ölçümle seçin. Laboratuvarda 200 MB görünen süreç, log seviyesi DEBUG açılınca veya buffer büyüyünce ikiye katlanabilir.
Ağ tarafında network_mode: host ROS discovery için cazip görünür; izolasyonu siler. Mümkünse bridge network + bilinen port publish; DDS / ROS_DOMAIN_ID çakışmalarını host mode ile “çözmek” yerine domain id disiplinine yatırım yapın.
Layer cache ve CI süresi
Multi-stage’in ikinci kazancı güvenlik değil, hızdır: requirements.txt değişmeden pip install katmanı cache’ten gelir. CI’da cache-from / registry cache kullanmazsanız her PR’da sıfırdan derleme hem dakika hem elektrik yer. Edge cihazlarda local build yapıyorsanız aynı disiplin geçerli — gece yarısı Jetson fan’ının tam gaz dönmesi genelde “COPY . .” satırının gereksiz yere üstte olmasındandır. Bağımlılık dosyalarını önce kopyalayın, kaynak kodu sonra.
İmzalı / immutable tag stratejisi (1.4.2 ve ayrıca 1.4.2-sha-abc12) rollback’i netleştirir. “Dün geceki latest” diye bir şey yoktur; dün geceki digest vardır.
Kapanış
Jetson / edge Docker sıkılaştırması üç cümlede özetlenir: gereksiz paketi imaja sokma, süreci root’suz çalıştır, yetkiyi (device, cap, privileged) gerekçeyle aç. Boyut küçültme bu yolun yan ürünüdür; asıl kazanç öngörülebilir attack surface ve dolmayan disklerdir. Distroless posterine bakıp CUDA stack’ini kırmaktansa, slim + multi-stage + non-root ile sahada ayakta kalan imaj daha iyidir.