2 Aralık 2025 Salı

Passkey (WebAuthn/FIDO2) ile Parolasız Giriş: Next.js Üzerinde Adım Adım Kurulum

Passkey nedir ve neden önemlidir?

Parolasız kimlik doğrulama, son yılların en önemli güvenlik trendlerinden biri. Passkey teknolojisi (WebAuthn/FIDO2), kimlik doğrulamayı klasik parolaların ötesine taşıyarak kimlik avına dayanıklı ve kullanıcı dostu bir deneyim sunuyor. Apple, Google ve Microsoft’un ekosistemleriyle entegre çalışan passkey’ler; cihazdaki güvenli donanım veya güvenli alanı kullanarak anahtar çifti üretir ve web sitelerine girişte yalnızca özel anahtar cihazda kalır. Böylece kullanıcılar Touch ID/Face ID, Windows Hello veya Android’in biyometrik yöntemleriyle tek dokunuşla güvenli giriş yapabilir.

Nasıl çalışır? (Kısa teknik özet)

Passkey, tarayıcıların sunduğu WebAuthn API üzerinden etkileşim kurar. Site (Relying Party), kayıt sırasında tarayıcıya bir “challenge” ve alan adı (rpID) gönderir. Kullanıcının cihazı bir anahtar çifti üretir; genel anahtar sunucuya kaydedilir, özel anahtar cihazda kalır. Giriş esnasında sunucu yeni bir “challenge” üretir; cihaz bu “challenge”ı özel anahtarla imzalar ve sunucu imzayı doğrular. Bu yapı sayesinde şifre sızması, parola doldurma saldırıları ve kimlik avı riskleri önemli ölçüde azalır.

Önkoşullar ve mimari

Bu rehberde Next.js 14 (App Router) üzerinde örnek bir passkey akışı kuracağız. İhtiyacınız olanlar: Node.js 18+, Next.js projesi, HTTPS (geliştirirken localhost desteklenir), bir veritabanı (ör. PostgreSQL, MongoDB) ve WebAuthn yardımcı kütüphaneleri. Üretimde rpID değeriniz, gerçek alan adınız (ör. example.com) olmalı; doğrulama başarısızlıklarının büyük kısmı rpID/domain uyumsuzluğundan kaynaklanır.

Adım 1: Kurulum ve bağımlılıklar

Örnek projeyi başlatmak için npx create-next-app@latest passkey-demo komutunu kullanın. Ardından sunucu ve istemci tarafı için popüler bir yardımcı set olan @simplewebauthn/server ve @simplewebauthn/browser paketlerini ekleyin: npm i @simplewebauthn/server @simplewebauthn/browser. Ortam değişkenleri için RP_NAME ve RP_ID tanımlayın (ör. RP_NAME="Passkey Demo", RP_ID="localhost" veya üretimde example.com).

Adım 2: Kayıt (Registration) akışı

Kayıt akışı iki uç noktadan oluşur: seçenek üretimi ve doğrulama. Sunucuda önce generateRegistrationOptions ile kullanıcıya özel bir challenge ve seçenekler oluşturulur. Örnek kullanım: const opts = generateRegistrationOptions({ rpName, rpID, userID, userName, attestationType: 'none', authenticatorSelection: { residentKey: 'preferred', userVerification: 'preferred' } }). Bu opts istemciye döndürülür ve tarayıcıda startRegistration(opts) çağrısı yapılır. Tarayıcı, cihazın güvenli alanında anahtar çifti üretir ve sonucu (credential) sunucuya gönderir.

Doğrulama aşamasında sunucuda verifyRegistrationResponse ile imza ve köken (origin) kontrolü yapılır. Başarılıysa kullanıcının hesabına credentialID, publicKey, signCount gibi alanları kaydedin. Birden fazla cihaza passkey eklenmesini desteklemek için kullanıcı başına birden çok credential saklamak iyi bir pratiktir.

Adım 3: Giriş (Authentication) akışı

Giriş için benzer şekilde önce generateAuthenticationOptions çağrılır. Kullanıcıya ait credential’lar biliniyorsa allowCredentials listesi ile sınırlandırabilir veya cihazın keşfedilebilir kimlik bilgilerini (discoverable credentials) desteklemek için boş bırakabilirsiniz. İstemci tarafında startAuthentication(opts) çalıştırılır ve elde edilen yanıt sunucuya doğrulama için gönderilir.

Sunucuda verifyAuthenticationResponse ile imza, challenge, origin, rpID ve sayacın (signCount) ilerleyişi kontrol edilir. Başarılı doğrulamada kullanıcı oturumunu başlatın ve credential’ın signCount değerini güncelleyin. Geriye dönük saldırıları önlemek için aynı imzayı tekrar kabul etmeyin.

İyi uygulamalar (Security + UX)

- HTTPS zorunludur: Üretimde daima HTTPS kullanın; rpID alan adınız ile origin (ör. https://example.com) örtüşmelidir. Geliştirmede localhost istisna olarak desteklenir.
- Biyometrik doğrulama: userVerification: 'required' seçeneği güvenliği artırır ancak bazı eski cihazlarda uyumluluğu azaltabilir. Dengeli yaklaşım için 'preferred' iyi bir başlangıçtır.
- Platform ve geçiş anahtarları: Kullanıcılara hem cihaz içi (platform) hem de harici güvenlik anahtarlarıyla kayıt seçeneği sunun.
- Hesap kurtarma: Passkey harika bir deneyim sunar; yine de e‑posta tabanlı oturum açma bağlantısı veya sınırlı süreli OTP gibi bir kurtarma kanalı tutun.
- Çoklu cihaz: iCloud Anahtar Zinciri veya Google Password Manager senkronizasyonu sayesinde kullanıcı farklı cihazlardan giriş yapabilir; bu durumda kullanıcı akışını basit ve yönlendirici metinlerle destekleyin.

Test, hata ayıklama ve dağıtım

Geliştirme sırasında WebAuthn’ı about://webauthn veya Chrome’un Geliştirici Araçları altındaki Sanal Kimlik Doğrulayıcı ile test edebilirsiniz. Gerçek cihaz testi için ngrok gibi tünelleme araçlarıyla geçici bir HTTPS alan adı edinip RP_ID’yi bu alan adına ayarlayın. iOS 16+, Android 9+ ve modern masaüstü tarayıcılar passkey’i destekler. Üretime alırken CORS, SameSite ve Secure bayraklı çerez ayarlarını kontrol edin; kimlik doğrulama uç noktalarınızı rate limit ve CSRF koruması ile güçlendirin.

Sık karşılaşılan hatalar ve çözümleri

- Invalid Relying Party ID: rpID ile sitenin alan adı eşleşmiyordur. Alt alan adlarında rpID üst etki alanı olabilir (ör. app.example.com için example.com).
- NotAllowedError: Kullanıcı tarayıcı diyalogunu iptal etmiştir veya zaman aşımı yaşanmıştır. İstemci tarafında daha anlaşılır hata mesajları ve tekrar dene düğmesi gösterin.
- User verification required: Sunucuda userVerification 'required' iken cihaz biyometrik doğrulama sunmuyorsa 'preferred' ile test edin.
- Counter mismatch: signCount geriye düştüyse credential’ı güvenlik gerekçesiyle askıya alın ve kullanıcıdan yeniden kayıt isteyin.

Sonuç

Passkey, güvenliği artırırken kullanıcı deneyimini hızlandıran güçlü bir yaklaşım. Next.js ile WebAuthn/FIDO2 entegrasyonu birkaç uç nokta ve doğru yapılandırmayla kısa sürede hayata geçebilir. Bu rehberdeki adımlarla kayıt ve giriş akışlarını kurabilir, üretimde HTTPS, rpID, sayım ve köken kontrolleriyle sisteminizi sertleştirebilirsiniz. Parolasız geleceğe geçiş için en iyi zaman, kullanıcılarınız hazır ve modern tarayıcılar destekliyorken bugündür.

1 Aralık 2025 Pazartesi

Docker Buildx ile Çok Mimarili Konteyner İmajı Oluşturma ve GitHub Actions ile Otomasyon

Giriş: Neden Çok Mimarili İmaj?

Apple Silicon (ARM64) cihazların, bulut sağlayıcıların ve edge cihazların yükselişi, tek mimariye derlenmiş konteyner imajlarının yeterli olmadığı bir dönemi başlattı. Uygulamanızı hem linux/amd64 hem de linux/arm64 üzerinde sorunsuz çalıştırmak istiyorsanız, Docker Buildx ve QEMU emülasyonu devreye giriyor. Bu yazıda, yerelde hızlıca çok mimarili imaj üretecek, ardından GitHub Actions ile her push veya tag’de otomatik olarak registry’ye yayınlayacak bir kurulum yapacağız.

Önkoşullar ve Temel Kavramlar

Başlamadan önce sisteminizde Docker Engine veya Docker Desktop’ın güncel bir sürümü kurulu olmalı. Buildx varsayılan olarak Docker ile gelir, ancak Linux kullanıcıları için docker buildx komutunun aktif olduğundan emin olun. Yerelde farklı mimariler için derleme yaparken QEMU desteği gerekir; Buildx bunu otomatik konfigüre edebilir. Ayrıca Docker Hub veya GHCR (GitHub Container Registry) gibi bir kayıt defterinde hesabınız ve kimlik bilgisi gerekecek. “Mimari” derken kastedilen: Intel/AMD tabanlı sunucular için amd64, Apple M serisi ve çoğu ARM tabanlı cihaz için arm64.

Dockerfile: Çok Aşamalı ve Mimariden Bağımsız

Örnek olarak küçük bir Go uygulaması için çok aşamalı bir Dockerfile kullanalım. Go, cross-compile’a yatkın olduğu için çok mimarili imajlarda pratiktir. Buildx, derleme sırasında TARGETPLATFORM ve TARGETARCH gibi değişkenleri otomatik olarak geçirir.

# syntax=docker/dockerfile:1.6
FROM golang:1.22-alpine AS build
WORKDIR /src
COPY . .
# CGO'yu kapatıp hedef mimariyi Buildx'ten alıyoruz
ARG TARGETARCH
ENV CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go build -o /out/app .

FROM alpine:3.20 AS runtime
RUN adduser -D -u 10001 app
USER app
COPY --from=build /out/app /app
EXPOSE 8080
ENTRYPOINT ["/app"]

Yukarıdaki Dockerfile, cache mount’larını kullanarak derlemeleri hızlandırır, root olmayan bir kullanıcı ile çalıştırır ve minimum imaj boyutu sağlar. Benzer bir yaklaşımı Node.js, Python veya Rust projelerinde de çok aşamalı yapı ile uygulayabilirsiniz.

Buildx’i Etkinleştirme ve Yerelde Test

Önce Buildx builder’ını oluşturun ve QEMU’yu başlatın:

docker buildx create --name xbuilder --use
docker buildx inspect --bootstrap

Ardından çok mimarili imajı derleyip bir kayıt defterine itin. Örnek olarak Docker Hub kullanıyorsanız:

docker login
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t KULLANICI_ADI/uygulama:1.0.0 \
-t KULLANICI_ADI/uygulama:latest \
--push .

İmajı emülasyonla farklı mimarilerde çalıştırmayı test edebilirsiniz:

docker run --rm --platform linux/arm64 KULLANICI_ADI/uygulama:1.0.0 --help

GitHub Actions ile Otomatik Yayın

Süreci otomatikleştirmek için depo köküne .github/workflows/build.yml adında bir iş akışı ekleyin. Aşağıdaki örnek, GHCR’ye push eder; Docker Hub için registry ve kimlik bilgilerini uyarlayın.

name: build-and-push-multi-arch
on:
push:
branches: ["main"]
tags: ["v*"]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=semver,pattern={{version}}
type=ref,event=branch
type=raw,value=latest,enable={{is_default_branch}}
- uses: docker/build-push-action@v6
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

Bu iş akışı; QEMU’yu kurar, Buildx’i etkinleştirir, GHCR’ye giriş yapar, semantik veya branch tabanlı etiketleri otomatik üretir ve iki mimari için imajı derleyip yayınlar. Docker Hub kullanıyorsanız registry satırını kaldırıp username/password için DOCKERHUB_USERNAME ve DOCKERHUB_TOKEN gibi secret’lar tanımlayın.

İnce Ayar: Performans, Güvenlik ve Boyut

Derlemeleri hızlandırmak için cache kullanımı kritik önemdedir. Yerelde --cache-to ve --cache-from bayrakları veya GitHub Actions’ta type=gha ile katmanları önbelleğe alın. .dockerignore dosyası ile gereksiz dosyaları dışarıda bırakın. Güvenlik açısından root olmayan kullanıcı kullanmak, yalnızca gerekli portları açmak, en küçük taban imajlarını (ör. alpine veya distroless) tercih etmek, SBOM ve kaynak kanıtı için --sbom=true ve --provenance=true kullanmak iyi pratiklerdir. İmajlarınızı imzalamak için cosign ile CI adımı ekleyebilirsiniz. Etiket stratejisinde hem latest hem de v1.2.3 gibi sürüm etiketlerini birlikte yayınlamak, geriye dönük izleme ve hızlı geri dönüş (rollback) sağlar.

Yayına Alındıktan Sonra Doğrulama

Yayınlanan imajın manifest listesine bakarak gerçekten çok mimarili olup olmadığını doğrulayın: docker buildx imagetools inspect ghcr.io/HESAP/REPO:latest. Çıktıda hem linux/amd64 hem de linux/arm64 gördüğünüzde her şey yolundadır. Üretim ortamında çekme yapan sistemlerin doğru mimariyi otomatik seçeceğini unutmayın.

Sonuç

Docker Buildx, modern çok mimarili dünyada tek komutla iki farklı platforma hitap eden imaj üretmeyi kolaylaştırır. GitHub Actions ile birleştirildiğinde, her commit veya sürümde otomatik ve tekrarlanabilir bir yayın hattı elde edersiniz. Bu yaklaşım, M serisi Mac’lerde yerel geliştirmeyi hızlandırırken, bulut ve edge ortamlarında tutarlı dağıtım sağlar. Küçük dokunuşlarla (önbellek, minimal taban imaj, imzalama) performansı artırabilir ve güvenliği güçlendirebilirsiniz.

30 Kasım 2025 Pazar

Passkey (WebAuthn) ile Şifresiz Giriş: Next.js ve SimpleWebAuthn ile Uçtan Uca Kurulum

Passkey (WebAuthn) ile Şifresiz Giriş: Adım Adım Uygulama Rehberi

Parola yorgunluğu, kimlik avı ve SMS tabanlı doğrulamanın zayıflıkları derken, modern web uygulamalarında şifresiz giriş kaçınılmaz hale geldi. Passkey’ler, WebAuthn ve FIDO2 standartlarıyla desteklenen, biyometri veya cihaz kilidiyle korunan anahtar çiftlerine dayanır. Kullanıcı deneyimini hızlandırır, kimlik avına dayanıklıdır ve iCloud Anahtar Zinciri ile Google Password Manager gibi yöneticiler arasında senkronize olabilir. Bu yazıda, Next.js ve SimpleWebAuthn kütüphanesi ile uçtan uca bir passkey (WebAuthn) entegrasyonunu nasıl kuracağınızı adım adım anlatıyorum.

Neden Passkey?

Passkey, kullanıcının cihazında saklanan bir özel anahtar ile sunucunun sakladığı açık anahtarın eşleşmesine dayanır. Parola gönderilmez, dolayısıyla veri tabanı sızıntılarında parolaların çalınması gibi riskler ortadan kalkar. Kullanıcı cihazında biyometri (Face ID, Touch ID), donanım anahtarı (YubiKey) veya cihaz PIN’i ile doğrulama yapar. Tarayıcı ve platform desteği artık yaygınlaştı; Chrome, Safari ve Firefox, iOS/Android ve masaüstü işletim sistemlerinde kullanılabiliyor.

Mimari ve Gereksinimler

WebAuthn iki ana akış içerir: kayıt (registration) ve kimlik doğrulama (authentication). Her akışta sunucu benzersiz bir challenge üretir, istemci tarafında tarayıcı navigator.credentials API’si ile doğrulama cihazıyla imza atılır ve bu yanıt sunucuda doğrulanır. Üretimde HTTPS zorunludur ve RP ID (Relying Party ID) alan adınızla birebir eşleşmelidir (ör. rpID = example.com).

Teknoloji Seçimi

Örnek kurulum için Next.js 14 (Route Handlers veya App Router), sunucu tarafında @simplewebauthn/server, istemci tarafında @simplewebauthn/browser kullanılabilir. Veritabanı olarak Postgres veya bir KV deposu tercih edebilirsiniz. Saklanacak başlıca alanlar: kullanıcı kimliği, credentialID, publicKey, counter ve tercihen cihaz/metaveri.

Kayıt Akışı (Registration)

1) Kullanıcı e-posta/ID ile kayıt başlatır. Sunucu generateRegistrationOptions ile seçenekleri üretir, challenge’ı geçici olarak saklar ve istemciye döner. Örnek:

const opts = generateRegistrationOptions({ rpName: 'Uygulama Adı', rpID: 'example.com', userName: 'ali', userID: 'user-123', attestationType: 'none', authenticatorSelection: { residentKey: 'preferred', userVerification: 'preferred', authenticatorAttachment: 'platform' } });

2) İstemci, tarayıcıda @simplewebauthn/browser yardımıyla kullanıcıdan biyometri izni ister ve kimlik bilgisi oluşturur:

const attResp = await startRegistration(opts);

3) Sunucu, verifyRegistrationResponse ile gelen cevabı doğrular; doğrulama başarılıysa credentialID, publicKey ve counter değerlerini kullanıcıyla ilişkilendirerek kalıcı olarak saklar.

Giriş Akışı (Authentication)

1) Kullanıcı giriş sayfasında e-posta/ID girer veya koşullu UI ile otomatik olarak öneri alır. Sunucu generateAuthenticationOptions ile yeni bir challenge üretir. İsteğe bağlı olarak yalnızca ilgili kullanıcının kayıtlı cihazlarını allowCredentials ile sınırlandırabilirsiniz.

2) İstemci tarafında çağrı yapılır:

const authResp = await startAuthentication(options);

3) Sunucu verifyAuthenticationResponse ile imzayı ve origin/rpID alanlarını doğrular, counter değerini günceller. Başarılıysa oturumu (cookie/JWT) kurar.

Koşullu UI (Conditional Mediation) ile Tek Tık Giriş

Chrome ve destekleyen tarayıcılarda, kullanıcı adı alanı odaktayken passkey önerilerini otomatik gösterebilirsiniz. Basitçe bir email input’unuz varken:

navigator.credentials.get({ publicKey: authOptions, mediation: 'conditional' });

Bunun çalışması için sayfanız HTTPS olmalı, autocomplete öznitelikleri doğru ayarlanmalı ve kullanıcı daha önce passkey kaydetmiş olmalıdır. Bu yöntem giriş sürtünmesini ciddi şekilde azaltır.

Güvenlik İpuçları ve En İyi Uygulamalar

- RP ID alan adınızla aynı olmalı; yerelde test ederken localhost kullanın veya geçerli bir sertifika ile alt alan adı hazırlayın.

- attestationType: 'none' çoğu senaryo için en iyisidir; gereksiz attestation verisi toplamayın.

- userVerification için 'required' yüksek güvenlikli sayfalar için uygundur (örn. ödeme, ayarlar). Genel girişte 'preferred' iyi bir dengedir.

- Kullanıcıların cihaz değiştirme/ekleme senaryoları için birden fazla passkey kaydına izin verin ve kurtarma seçenekleri (e-posta bağlantısı veya destek akışı) sunun.

- Rate limit, yeniden oynatma (replay) engelleme, kaynak (origin) ve challenge ömrünü doğrulamayı ihmal etmeyin.

Hata Ayıklama ve Test

- SecurityError: The operation is insecure genelde HTTPS veya RP ID uyuşmazlığını gösterir.

- NotAllowedError kullanıcı etkileşimi yokken veya işlemi iptal ettiğinde görülür; buton tıklamasıyla tetikleyin.

- Unknown authenticator veya eşleşmeyen credentialID için doğru kullanıcıyla ilişkilendirme yapıldığından emin olun.

- Tarayıcı konsolu ve about://webauthn (Chrome) test araçları ile sanal güvenlik anahtarı oluşturup akışları yerelde deneyebilirsiniz.

Performans ve UX

Passkey akışı minimal JSON veri alışverişine dayanır; SSR ve edge işleme ile gecikmeyi azaltabilirsiniz. Başarılı kayıt sonrası kullanıcının cihazı üzerinde parolayı da “kaldırmayı” önermek, geçişi hızlandırır. Kullanıcıya hangi cihazların kayıtlı olduğunu gösteren bir yönetim ekranı sunmak güveni artırır.

Sonuç

Passkey (WebAuthn) ile şifresiz giriş, güvenliği artırırken kullanıcı deneyimini de basitleştirir. Next.js ve SimpleWebAuthn ile kurulumu birkaç uç noktaya indirgenebilir: kayıt için seçenek üretme/doğrulama ve giriş için seçenek üretme/doğrulama. RP ID, HTTPS ve challenge yönetimi gibi kritik ayrıntılara dikkat ettiğiniz sürece, modern tarayıcılarda hızlı ve güvenli bir oturum altyapısı sağlayabilirsiniz.

29 Kasım 2025 Cumartesi

pgvector ile RAG Uygulaması: Docker Compose ile PostgreSQL 16 ve Basit Semantik Arama API’si

RAG (Retrieval-Augmented Generation), büyük dil modellerinin (LLM) güncel ve alanınıza özgü verilerle daha doğru yanıtlar üretmesini sağlar. Bu yaklaşımda, soruyu bir vektöre dönüştürür, vektör veritabanından benzer içerikleri geri çağırır ve modeli bu bağlamla beslersiniz. Özel bir vektör veritabanına ihtiyaç duymadan, PostgreSQL 16 + pgvector ile etkili bir semantik arama katmanı kurmak mümkündür. Bu yazıda, Docker Compose ile PostgreSQL’i ayağa kaldıracak, pgvector eklentisini etkinleştirecek ve basit bir API üzerinden semantik arama yapabileceğiz.

Neden PostgreSQL + pgvector? PostgreSQL hâlihazırda üretim ortamlarında yaygın, güvenilir ve güçlü bir ilişkisel veritabanıdır. pgvector eklentisi, vektör tipini, benzerlik metriklerini (cosine, L2, inner product) ve ivfflat/HNSW benzeri indeksleme stratejilerini destekler. Küçük ve orta ölçekli RAG projeleri için tek bir veritabanı üzerinde hem ilişkisel hem de vektörel sorgular yürütmek operasyonel anlamda sade ve maliyet-etkindir.

Önkoşullar: Makinenizde Docker ve Docker Compose kurulu olmalı. Embedding üretimi için OpenAI hesabı (veya yerelde Ollama gibi bir çözüm) işinizi kolaylaştırır. Örneklerde OpenAI’nin “text-embedding-3-small” (1536 boyut) modelini referans vereceğiz; yerel seçenek kullanacaksanız embedding boyutunu ona göre ayarlamalısınız.

Adım 1: Docker Compose ile PostgreSQL 16 ve pgvector
Basit bir docker-compose.yml dosyası oluşturun ve şu servisi tanımlayın:
version: "3.9"
services:
  db:
    image: pgvector/pgvector:pg16
    environment:
      - POSTGRES_USER=rag
      - POSTGRES_PASSWORD=ragpass
      - POSTGRES_DB=ragdb
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:
Dosyayı kaydedip docker compose up -d komutunu çalıştırın. Bu imaj, pgvector eklentisi ile birlikte gelir.

Adım 2: pgvector’ü etkinleştirmek ve şema hazırlığı
Veritabanına bağlanın: psql -h localhost -U rag -d ragdb ve şu komutları çalıştırın:
CREATE EXTENSION IF NOT EXISTS vector;
OpenAI’nin “text-embedding-3-small” boyutuna uygun bir tablo oluşturun:
CREATE TABLE docs (
  id BIGSERIAL PRIMARY KEY,
  content TEXT NOT NULL,
  embedding vector(1536)
);
Arama performansı için ivfflat indeksini kurun (cosine metrik popüler bir tercih):
CREATE INDEX ON docs USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
İndeksin etkili çalışması için tabloyu analiz edin: ANALYZE docs;

Adım 3: Embedding üretimi ve veri ekleme
Örnek içerikler ekleyelim: ürün açıklamaları, SSS, teknik notlar vs. Python ile kısa bir betik yazabilirsiniz. OpenAI için mantık şu şekildedir:
- Metni al, client.embeddings.create(model="text-embedding-3-small", input=metin) ile vektörü üret.
- Vektörü PostgreSQL’e parametreli bir sorgu ile yaz: INSERT INTO docs(content, embedding) VALUES ($1, $2).
Yerel alternatif isterseniz, Ollama’da ollama pull nomic-embed-text diyerek bir embedding modeli çekebilir, http://localhost:11434/api/embeddings üzerinden benzer bir akış kurabilirsiniz. Dikkat: embedding boyutunu (ör. 768) tablo şemanızla tutarlı yapın.

Adım 4: Semantik arama sorgusu
Kullanıcı sorgusunu da embedding’e çevirin ve ORDER BY embedding <=> $1 ifadesiyle benzerliğe göre sıralayın. Örnek bir SQL:
WITH q AS (SELECT $1::vector AS v)
SELECT id, content
FROM docs, q
ORDER BY docs.embedding <=> q.v
LIMIT 5;
Burada <=>, pgvector’ün benzerlik operatörüdür (cosine için mesafe). Bu sonuçları LLM’e bağlam olarak verip RAG yanıtı oluşturabilirsiniz.

Adım 5: Basit bir API ile uçtan uca akış
Hızlı bir prototip için Python FastAPI idealdir. Akış şöyledir:
1) POST /search: query alır, embedding üretir, PostgreSQL’den top-k döner.
2) POST /ask: query ve top-k bağlamı alır, seçtiğiniz LLM (OpenAI veya yerel) ile yanıt üretir.
Üretimde, sonuçları önbelleğe almak (ör. Redis), indeks lists değerini veri büyüklüğüne göre artırmak ve maintenance_work_mem, shared_buffers gibi PostgreSQL ayarlarını optimize etmek önemlidir.

İleri seviye ipuçları
- HNSW: pgvector 0.7+ sürümlerinde HNSW desteği bulunur; okuma gecikmesini düşürür, ancak indexleme süresi ve bellek kullanımı artar. Benchmark yapmadan geçiş yapmayın.
- Normalize embedding: Cosine benzerliğinde vektörleri normalize etmek sonuç tutarlılığını artırabilir.
- Chunking ve metadata: Belgeleri 300–800 token aralığında parçalara bölün. Kaynak, tarih, başlık gibi metadata alanlarını tabloya ekleyin ve sonuçlarda gösterin.
- Güncelleme stratejisi: Sık değişen veriler için upsert akışı oluşturun; embedding’i yalnızca içerik değiştiğinde güncelleyin.
- Güvenlik: Üretimde veritabanını dışarıya kapatın, SSL kullanın, sıkı rol ve politika tanımları yapın.

Sonuç
PostgreSQL 16 ve pgvector ile, ek bir servis karmaşıklığına girmeden güçlü bir semantik arama ve RAG katmanı kurabilirsiniz. Docker Compose yapılandırması hızlı kurulum sağlar; embedding üretimi için OpenAI veya yerel modelleri kullanabilirsiniz. Üzerine basit bir API ekleyerek hem prototip hem de üretim öncesi pilot projelerinizi hızla hayata geçirmeniz mümkün. Doğru indeks, boyut ve ayarlarla, pgvector küçük-orta ölçekli prodüksiyon yüklerini rahatlıkla karşılayacaktır.

28 Kasım 2025 Cuma

RAG ile Türkçe Soru-Cevap Sistemi Kurma: Vektör Veritabanı, Yeniden Sıralama ve Prompt Tasarımı

RAG (Retrieval-Augmented Generation), büyük dil modellerinin (LLM) güncel ve alanınıza özel bilgilerle desteklenmesini sağlayan, üretken yapay zekâ projelerinde giderek standarda dönüşen bir yaklaşımdır. Bu yazıda, Türkçe odaklı bir doküman arama ve soru-cevap sistemini RAG mimarisiyle nasıl kurabileceğinizi; veri hazırlığından vektör veritabanına, yeniden sıralamadan (re-ranking) prompt tasarımına kadar adım adım anlatıyorum.

Amaç, kullanıcı sorusuna dayanarak şirket içi PDF’ler, politika metinleri, ürün katalogları veya destek dökümanları içinden ilgili pasajları bulmak ve LLM’nin yalnızca bu pasajları referans alarak doğru, denetlenebilir cevaplar üretmesini sağlamaktır. Böylece hem halüsinasyonları azaltır hem de cevaplara kaynak gösterebilirsiniz.

Mimari Özeti: RAG iki parçadan oluşur. Birincisi bilgi erişimi (retrieval): Belgeleri parçalayıp (chunking), vektörlerine dönüştürerek bir vektör veritabanına koyar ve sorguya en yakın aday pasajları getirir. İkincisi jenerasyon (generation): LLM, gelen pasajları bağlam olarak kullanıp nihai cevabı üretir. İsteğe bağlı üçüncü bir katman olan yeniden sıralama (re-ranking) ile en iyi adayları üst sıralara taşıyarak doğruluğu yükseltirsiniz.

1) Veri Toplama ve Temizleme: PDF, HTML, Word veya düz metin kaynaklarınızı tek bir havuzda toplayın. Başlık, bölüm, tarih ve izin seviyesi gibi meta verileri koruyun. OCR gerekiyorsa hatalı karakterleri düzeltin, tabloları metne uygun biçimde dönüştürün. Aynı belgenin eski sürümlerini işaretleyerek sürüm çakışmalarını engelleyin.

2) Parçalama (Chunking): Türkçe dilinde bağlamı korumak için paragraf temelli veya cümle temelli parçalama tercih edin. 400–800 token aralığı pratikte iyi sonuç verir; çok küçük parçalarda bağlam kaybolur, aşırı büyük parçalarda ise arama isabeti düşer. Kayma penceresi (overlap) 50–100 token aralığında seçildiğinde cümle bütünlüğü ve referanslar daha sağlam kalır.

3) Gömme (Embeddings) Seçimi: Çok dilli Sentence Transformers tabanlı modeller veya Türkçe uyumlu modern embedding modelleri tercih edin. Türkçe morfolojisi nedeniyle kök/ek varyasyonlarını iyi yakalayan çok dilli modeller pratikte güçlüdür. Vektörleri L2 normla normalize etmeniz kozinüs benzerliği için istikrar sağlar. Boyut (dimensionality) arttıkça isabet artsa da depolama ve gecikme maliyeti yükselir; üretim için 384–1024 aralığı dengelidir.

4) İndeksleme ve Vektör Veritabanı: FAISS ile lokal hızlı prototipleme yapabilir, üretimde Qdrant, Weaviate, Pinecone ya da Elasticsearch’ün yoğun vektör (dense) alanlarını kullanabilirsiniz. HNSW veya IVF-PQ gibi yaklaşık en yakın komşu (ANN) indeksleri gecikmeyi düşürür. Meta veri filtreleme (ör. dil, departman, tarih) ile hassas eşleşme yaparak alakasız sonuçları erkenden eleyin.

5) Hibrit Arama: Tek başına vektör benzerliği bazen anahtar kelime ağırlıklı soruları ıskalayabilir. BM25 + vektör aramayı birleştirerek iki dünyanın en iyisini alabilirsiniz. RRF (Reciprocal Rank Fusion) veya ağırlıklı skor birleştirme ile son aday listesini oluşturun. MMR (Maximal Marginal Relevance) kullanarak çeşitliliği artırın; böylece benzer pasajlar yerine farklı açılardan destekleyen pasajlar üst sıralara gelir.

6) Yeniden Sıralama (Re-ranking): İlk 50–200 adayı, küçük ama hassas bir çapraz-enkoder re-ranker modeliyle yeniden puanlayın. Re-ranker, sorgu ile pasaj arasındaki anlam ilişkisini derinlikli değerlendirir ve isabeti gözle görülür şekilde artırır. Özellikle Türkçe sorgularda, re-ranker kullanımı yanlış pozitifleri ciddi biçimde azaltır.

7) Prompt Tasarımı: Sistem talimatına “Sadece sağlanan bağlamdan yararlan, kaynak yoksa ‘yeterli bilgi yok’ de” gibi net kısıtlar ekleyin. Kullanıcı sorusu, seçilen pasajlar ve gerekirse kısa bir özet talimatı tek bir prompt içinde verilebilir. Her pasajın yanında kaynak kimliği (belge adı, sayfa, bölüm) tutarak yanıta otomatik kaynakça ekleyin; bu, güven ve denetlenebilirlik sağlar.

8) Cevap Üretimi ve Biçimlendirme: Uzun cevaplar için madde işaretleri, kısa cevaplar için net tek paragraf formatı tercih edin. Modelin “uydurma” eğilimini azaltmak için bağlam penceresini verimli kullanın; gerekirse soruyu alt-sorulara bölüp her alt-soru için mini retrieval akışı kurgulayın (multi-step RAG). Hassas alanlarda (hukuk, finans, sağlık) kesinlik dilini yumuşatın ve gerekiyorsa uyarı notu ekleyin.

9) Değerlendirme ve İzleme: Recall@k, MRR, nDCG gibi arama metrikleri ile konteks isabetini ölçün. Yanıt kalitesi için bağlam kapsamı, doğruluk ve kaynak tutarlılığına bakın. Üretim ortamında RAG değerlendirme çerçeveleri (ör. otomatik değerlendirme ve örneklem tabanlı insan denetimi) kurarak sürekli iyileştirme döngüsü oluşturun. Yanlış eşleşen pasajları etiketleyip yeniden eğitime dahil ederek sistematik hataları azaltın.

10) Performans, Maliyet ve Bakıma Dair İpuçları: Sorgu tarafında embedding önbelleği, sonuç tarafında yanıt önbelleği (semantic cache) maliyeti düşürür. ANN indeks parametrelerini (efSearch, nprobe vb.) gecikme/hedef isabet dengesine göre ayarlayın. Kenar cihazlarda veya düşük bütçede 4-bit/8-bit quantized LLM’ler iş görür. Büyük kurumsal koleksiyonlarda artımlı indeks güncellemeleri ve arka plan yeniden inşa stratejisi planlayın.

11) Güvenlik ve Uyumluluk: Kurumsal RAG’da erişim kontrolünü indeks katmanında uygulayın; kullanıcının yetkisi olmayan belgeler retrieval aşamasına hiç girmesin. PII maskeleme ve günlükleme (audit) politikalarını belirleyin. Oran sınırlama (rate limiting) ve anomali tespiti ile kötüye kullanımı engelleyin.

Sık Yapılan Hatalar: Çok büyük chunk boyutları kullanmak, yalnızca vektör aramaya güvenmek, re-ranker atlamak, prompt’ta kaynak gösterimi istememek ve üretim izleme metriklerini kurmamak. Ayrıca embed modeli ile arama dili uyumsuz olduğunda isabet hızla düşer; çok dilli kullanımda model seçimini A/B testleriyle doğrulayın.

Sonuç: RAG, Türkçe belgelerle çalışan soru-cevap sistemleri için pratik, ölçeklenebilir ve denetlenebilir bir çözüm sunar. Doğru chunking, iyi seçilmiş embedding, hibrit arama ve re-ranking üçlüsü; üzerine titizlikle kurgulanmış prompt ve değerlendirme yönergeleri ile birleştiğinde, hem doğruluk hem de kullanıcı güveni açısından sınıf atlatır. Küçük bir pilot ile başlayıp metrikler ışığında iteratif optimize ederek kısa sürede üretime hazır, kaynaklı ve güvenilir bir RAG çözümü elde edebilirsiniz.

27 Kasım 2025 Perşembe

Docker Buildx ile Çoklu Mimarili İmaj Üretimi, İmzalama ve SBOM: Uçtan Uca Rehber

Giriş

Apple Silicon (arm64) ve x86_64 (amd64) dünyasının iç içe geçtiği günümüzde, tek bir Docker imajını birden fazla mimari için üretmek artık bir lüks değil, gereklilik. Üstelik iş yalnızca imajı derlemekle bitmiyor; tedarik zinciri güvenliği gereksinimleri sebebiyle imajları imzalamak ve yazılım malzeme listesi (SBOM) üretmek de kritik hale geldi. Bu rehberde, Docker Buildx ile çoklu mimari imaj üretmeyi, cosign ile imzalamayı ve syft ile SBOM oluşturup imaja iliştirmeyi adım adım anlatıyorum.

Önkoşullar

Makinenizde güncel Docker (mümkünse 24+), Buildx eklentisi (Docker Desktop veya docker-buildx plugin), ve emülasyon için QEMU kurulu olmalı. Çapraz derleme için binfmt yardımıyla arm64/amd64 emülasyonu etkinleştirilebilir. Ayrıca imzalama için cosign, SBOM için syft ve opsiyonel zafiyet taraması için grype kurmanız faydalı olacaktır.

Kontrol komutları: docker buildx version, mevcut builder'ları görmek için docker buildx ls. Gerekirse yeni bir builder oluşturun: docker buildx create --name multiarch --driver docker-container --use. Emülasyon için: docker run --privileged --rm tonistiigi/binfmt --install arm64,amd64.

Çoklu Mimarili İmaj Derleme ve Push

Çoklu mimari imaj üretmenin en pratik yolu Buildx ile manifest list oluşturmaktır. Örnek komut: docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/kullanici/uygulama:1.0 --push . Bu komut, her mimari için ayrı imaj derleyip registry'e yükler ve üzerinde mimari bilgisi bulunan tek bir etiket altında (manifest list) birleştirir.

İşin sorunsuz ilerlemesi için taban imajınızın da çoklu mimari desteklemesi gerekir. Örneğin alpine, debian ya da popüler dil imajlarının çoğu arm64/amd64 sürümleri sağlar. Derleme aşamasında Go/Node/Rust gibi dillerde hedef mimariyi belirtmek için ilgili araçların bayraklarından yararlanın; örneğin Go için --build-arg ile GOOS=linux, GOARCH=arm64 gibi değişkenler verilebilir.

Derleme süresini kısaltmak ve tekrarlayan işlerden kaçınmak için BuildKit cache’i kullanın: --cache-to type=registry,ref=ghcr.io/kullanici/uygulama:buildcache,mode=max --cache-from type=registry,ref=ghcr.io/kullanici/uygulama:buildcache. Bu, özellikle CI/CD boru hatlarında çok fark yaratır.

Manifest List Doğrulama

Push tamamlandığında manifest içeriğini şöyle inceleyebilirsiniz: docker buildx imagetools inspect ghcr.io/kullanici/uygulama:1.0. Çıktıda linux/amd64 ve linux/arm64 varyantlarını görmelisiniz. Her cihaz, kendi mimarisine uygun katmanı otomatik olarak çekecektir.

Cosign ile İmaj İmzalama ve Doğrulama

Tedarik zinciri güvenliğinde ilk adım imajları imzalamaktır. Cosign iki biçimde çalışabilir: anahtarlı (key-pair) ve keyless (OIDC). Hızlı başlangıç için keyless önerilir. GitHub veya Google hesabınızla kimlik doğrulama yaparak: COSIGN_EXPERIMENTAL=1 cosign sign ghcr.io/kullanici/uygulama:1.0. Bu komut, imza verisini registry üzerinde imaj referansına bağlı şekilde saklar.

Doğrulama için: cosign verify ghcr.io/kullanici/uygulama:1.0. Çıktıda sertifika zinciri ve imzanın geçerliliği görünmelidir. İmzalama politikanızı CI’da zorunlu kılmak, üretim öncesi kabul kriterlerinin önemli bir parçasıdır.

Syft ile SBOM Üretimi ve İliştirme

SBOM (Software Bill of Materials), imajın içindeki bağımlılıkların envanteridir. Syft ile tek satırda oluşturabilirsiniz: syft ghcr.io/kullanici/uygulama:1.0 -o spdx-json > sbom.spdx.json. Bu dosyayı imaja iliştirmek için cosign attest kullanın: cosign attest --predicate sbom.spdx.json --type spdx ghcr.io/kullanici/uygulama:1.0.

SBOM’u doğrulamak veya çekmek için: cosign verify-attestation ghcr.io/kullanici/uygulama:1.0 ve cosign download attestation ghcr.io/kullanici/uygulama:1.0. SBOM, güvenlik taraması (grype, trivy) ve uyumluluk kontrolleri için referans noktasıdır.

CI/CD Entegrasyonu (GitHub Actions Örneği)

GitHub Actions’da setup-buildx ve login adımlarını ekleyip ardından çoklu mimari derlemeyi tetikleyebilirsiniz. Tipik adımlar: registry’e giriş (docker/login-action), Buildx kurulum (docker/setup-buildx-action), cache ayarları, ardından docker/build-push-action ile platform: linux/amd64,linux/arm64 şeklinde build ve push. Sonraki adımlarda sigstore/cosign-installer ile cosign kurulumu, COSIGN_EXPERIMENTAL=1 cosign sign ve syft ile SBOM üretimi yer alabilir. Workflow gizli değişkenleriyle registry token’larını ve imza politikalarını yönetmeyi unutmayın.

İpuçları ve Yaygın Hatalar

- Taban imajı multi-arch değilse derleme bir mimaride başarılı olurken diğerinde başarısız olabilir. Alternatif taban imajları deneyin veya kendi tabanınızı üretin.

- QEMU emülasyonu derlemeyi yavaşlatabilir. Yerel arm64 runner veya native builder node’ları ile süreyi ciddi şekilde düşürebilirsiniz.

- Reproducible build için sabit sürümler ve kilit dosyaları (go.sum, package-lock.json, Cargo.lock) kullanın. Değişken sürümler, SBOM ve zafiyet taraması sonuçlarını dalgalandırır.

- Cache’i registry üzerinde tutmak, farklı runner’lar arasında tekrar derlemeyi azaltır. mode=max ile en agresif önbelleği etkinleştirebilirsiniz.

- İmza ve attestation objeleri için üretim ve test kayıtlarını ayırın. Etiketleme stratejinizde :dev, :staging, :prod gibi net kanallar oluşturun.

Sonuç

Docker Buildx ile çoklu mimari imaj üretmek, hem geliştirici deneyimini iyileştirir hem de farklı donanım platformlarında tek bir etiket üzerinden dağıtım yapmanızı sağlar. Cosign ile imzalama ve Syft ile SBOM üretimi ise tedarik zinciri güvenliğinizin bel kemiğidir. Bu üç adımı CI/CD boru hattınıza entegre ettiğinizde, yalnızca hızlı değil, aynı zamanda doğrulanabilir ve denetlenebilir bir yayın sürecine sahip olursunuz. Bugünden başlayın; manifest list, imza ve SBOM’u varsayılanınız haline getirin.

26 Kasım 2025 Çarşamba

GitHub Actions ile Çok Mimarili (Multi-Arch) Docker İmajı Oluşturma: Adım Adım Rehber

Modern uygulamalar artık tek bir mimariyle sınırlı kalmıyor. Geliştiriciler, yerel ortamda Apple Silicon (ARM64) üzerinde çalışırken üretimde x86_64 (AMD64) tabanlı sunuculara dağıtım yapabiliyor. Bu çeşitlilikte sorunsuz dağıtım için tek etiket altında birden fazla mimariyi kapsayan "çok mimarili (multi-arch)" Docker imajları kritik hale geliyor. Bu rehberde, GitHub Actions kullanarak multi-arch Docker imajlarını otomatik derleme, imzalama ve kayıt (registry) ortamına gönderme sürecini adım adım anlatıyorum.

Hedefimiz: Her push sonrasında, Docker Buildx ve QEMU emülasyonu ile linux/amd64 ve linux/arm64 platformları için imaj üretmek, doğru etiketleri (tag) eklemek, cache kullanarak derleme süresini kısaltmak ve imajı GHCR (GitHub Container Registry) ya da seçtiğiniz herhangi bir registry'ye göndermek.

Neden Çok Mimarili İmaj?

- Kullanıcılarınızın farklı donanımlarda sorunsuz çalışması için tek imaj etiketi yeterli olur. "docker pull" komutunu çalıştıran istemci, platformuna uygun manifesti otomatik çeker.

- CI/CD süreçlerinde tek kaynaklı doğrulama, test ve güvenlik taraması ile operasyon karmaşıklığını azaltırsınız.

- Tekil sürüm yönetimi sayesinde SLAs ve geri dönüş (rollback) süreçleri sadeleşir.

Önkoşullar

- Proje kök dizininde çalışır bir Dockerfile.

- GitHub Actions kullanabileceğiniz bir depo.

- GHCR kullanacaksanız paket yazma izni; varsayılan GITHUB_TOKEN yeterli olur.

- Tercihen: Semver etiketleri (örn. v1.2.3) ve ana dal (main) akışı.

Adım Adım GitHub Actions Workflow

Aşağıdaki örneği .github/workflows/docker.yml olarak kaydedin. Bu akış, push ve manuel tetiklemede devreye girer, QEMU ve Buildx kurar, GHCR'ye giriş yapar, meta bilgileri üretir ve imajı çok mimarili olarak yayınlar.

name: Build & Push Multi-Arch Image

on:
  push:
    branches: [ "main" ]
    paths:
      - "Dockerfile"
      - "src/**"
      - ".github/workflows/docker.yml"
  workflow_dispatch:

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

jobs:
  build:
    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 GHCR
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels)
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=sha
          labels: |
            org.opencontainers.image.source=${{ github.repositoryUrl }}

      - name: Build and push (multi-arch)
        id: build
        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=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
          cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
          provenance: true
          sbom: true

      # İsteğe bağlı: Keyless imaj imzalama (Sigstore Cosign)
      - name: Install Cosign
        uses: sigstore/cosign-installer@v3

      - name: Sign image (keyless)
        run: cosign sign --yes ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
        env:
          COSIGN_EXPERIMENTAL: "1"

Bu akış, Docker Buildx ile manifest listesi üretir; yani tek bir etikete push etseniz bile altında arm64 ve amd64 varyantları bulunur. "provenance: true" ve "sbom: true" seçenekleri tedarik zinciri şeffaflığı için yazılım malzeme listesi ve oluşturulma kanıtı ekler; güvenlik ve uyumluluk süreçlerinde büyük kolaylık sağlar.

Etiketleme Stratejisi ve Sürümleme

metadata-action, branch adına (örn. main), semantik sürüm etiketlerine (örn. v1.4.0) ve commit SHA'sına göre otomatik tag üretir. Üretimde "latest" tag'ini yalnızca yayın (release) akışlarında basmanızı öneririm; aksi halde test etiketleri ile karışabilir. Ayrıca, immutability sağlamak için SHA tabanlı tag'ler geri dönüş (rollback) senaryolarında hayati önem taşır.

Ön Bellekleme (Cache) ile Hız Kazanın

Build cache'i registry üzerinde saklamak, paralel ve ardışık derlemelerde ciddi zaman kazandırır. Dockerfile adımlarını, bağımlılık indirme ve derleme katmanlarını efektif kullanacak şekilde düzenleyin: Sık değişen kod katmanlarını sona, nadir değişen bağımlılık katmanlarını başa koymak cache verimini artırır.

Güvenlik: İmza, SBOM ve Tarama

Cosign ile keyless imzalama, GitHub'ın OIDC kimlik doğrulamasını kullanarak özel anahtar yönetimini basitleştirir. SBOM üretimi ise açık kaynak lisans takibi ve güvenlik açıkları yönetimi için temel veri sağlar. Buna ek olarak, ayrı bir adımda Trivy veya Grype ile imaj taraması yaparak pipeline'ınızı tamamlayabilirsiniz.

Hızlı Test: Pull ve Çalıştırma

Yerel makinenizde mimarinize göre doğru varyantı çekip çalıştırmak için:

# amd64 veya arm64 üzerinde aynı etiketi çekersiniz
docker pull ghcr.io/<kullanici>/<repo>:main
docker run --rm ghcr.io/<kullanici>/<repo>:main

Manifesti doğrulamak isterseniz "docker buildx imagetools inspect ghcr.io/<kullanici>/<repo>:main" komutunu kullanın; listede linux/amd64 ve linux/arm64 göreceksiniz.

Sık Karşılaşılan Hatalar ve Çözümler

- QEMU bulunamadı: setup-qemu-action adımını kaçırmış olabilirsiniz; sırayı kontrol edin.

- Permission denied (GHCR): packages: write izni ve login-action yapılandırmasını gözden geçirin. Özel registry kullanıyorsanız kullanıcı adı/şifre veya token değerlerini secrets altında tanımlayın.

- Cache çalışmıyor: "cache-from" ve "cache-to" referanslarının aynı olduğundan ve imaja erişim izniniz bulunduğundan emin olun. Ayrıca Dockerfile katman sırasını optimize edin.

- Çok büyük imaj boyutu: Multi-stage build, küçük base imajlar (alpine, distroless) ve "--strip" benzeri derleme optimizasyonlarıyla boyutu düşürün.

Sonuç

GitHub Actions ile multi-arch Docker imajları üretmek, hem geliştirme hem de üretim ortamlarında taşınabilirlik ve güvenilirlik sağlar. Buildx, QEMU, otomatik etiketleme, cache, SBOM ve isteğe bağlı imzalama adımlarıyla kurduğunuz bu zincir, modern DevOps pratiklerinin omurgasını oluşturur. Rehberi projelerinize uyarlayıp aşamalı olarak genişletirseniz, edge cihazlardan bulut altyapılarına kadar tek bir imaj politikasıyla yönetilebilir, sürdürülebilir bir dağıtım stratejisi elde edersiniz.