yazılar
Konteyneri Buluta Taşımak: ECR, ECS Fargate ve ALB
Eğitim sunumuna erişmek için → Ders 3 Slaytları Kaynak kod & sunumlar → github.com/Kaangml/docker-egitimi
Nereye Gidiyoruz?
Önceki derste local’de çalışan bir FastAPI imajı vardı: docker build, docker run, docker compose. Şimdi o imajı gerçek bir URL’e taşıyoruz — herkesin erişebileceği, yük altında ölçeklenebilen, sunucu yönetmek zorunda olmadığımız bir ortama.
Yol şu: ECR → ECS + Fargate → ALB → Public URL
AWS Konteyner Ekosistemi
Önce haritayı anlamak gerekiyor. Hangi servis ne işe yarıyor?
| AWS Servisi | Ne yapar? | Docker karşılığı |
|---|---|---|
| ECR (Elastic Container Registry) | Private image deposu | Docker Hub (özel) |
| ECS (Elastic Container Service) | Container çalıştırma ve yönetimi | docker run otomatik |
| Fargate | Sunucu yönetmeden container çalıştır | EC2 olmadan Docker |
| ALB (Application Load Balancer) | İstekleri container’lara dağıt | Nginx (yönetilen) |
Neden Fargate seçiyoruz? Alternatif EC2’dur — sunucu kiralarsın, üstüne Docker kurarsın, patch’lerini takip edersin. Fargate’de bunların hiçbiri yok; AWS altyapıyı halleder, sen sadece container konfigürasyonunu tarif edersin.
Adım 1: ECR’ye Push
İmajı önce AWS’nin private registry’sine göndermek gerekiyor. ECS oradan çekecek.
# Repository oluştur
aws ecr create-repository \
--repository-name image-classifier-api \
--region eu-central-1
# AWS kimlik bilgisiyle Docker'a login ol
aws ecr get-login-password --region eu-central-1 | \
docker login --username AWS \
--password-stdin \
$ACCOUNT.dkr.ecr.eu-central-1.amazonaws.com
# İmajı tag'le ve push et
docker tag image-classifier-api:latest \
$ACCOUNT.dkr.ecr.eu-central-1.amazonaws.com/image-classifier-api:latest
docker push \
$ACCOUNT.dkr.ecr.eu-central-1.amazonaws.com/image-classifier-api:latest
ACCOUNT değeri AWS hesap ID’n. aws sts get-caller-identity --query Account --output text ile öğrenebilirsin.
ECR’nin Docker Hub’dan farkı: IAM tabanlı erişim kontrolü ve KMS şifrelemesi. İmaj public değil; sadece doğru izinlere sahip servisler çekebilir.
Adım 2: ECS Kavramlarını Anlamak
ECS’te dört kavram var, hiyerarşik:
- Cluster — container’ların çalışacağı ortam (Fargate veya EC2)
- Task Definition — container’ın tarifnamesi: hangi imaj, kaç CPU, kaç RAM, hangi port, hangi env var’lar
- Task — Task Definition’dan ayağa kalkmış çalışan bir örnek
- Service — “Bu Task Definition’dan her zaman N tane çalışsın” kuralı
Service’in güçlü yanı şu: bir Task çöktüğünde Service onu fark edip yenisini başlatır. Desired count’u 2 tuttuğunda daima 2 Task ayakta olmaya çalışır.
Adım 3: Task Definition
Task Definition bir JSON belgesidir. AWS Console’dan form doldurarak da oluşturulabilir, ama CLI ile daha net görünüyor:
aws ecs register-task-definition \
--family image-classifier-api \
--requires-compatibilities FARGATE \
--network-mode awsvpc \
--cpu 1024 --memory 2048 \
--container-definitions '[
{
"name": "image-classifier-api",
"image": "'$ECR_URI'/image-classifier-api:latest",
"portMappings": [{"containerPort": 8080}],
"environment": [
{"name": "S3_BUCKET", "value": "my-images-bucket"}
]
}
]'
cpu: 1024 = 1 vCPU, memory: 2048 = 2 GB RAM. Fargate bu değerler üzerinden faturalandırır — task çalıştığı sürece, kullanıyor olsan da olmasan da.
network-mode: awsvpc Fargate’de zorunlu. Her task’a ayrı bir elastic network interface ve özel IP verilir.
Adım 4: Service ve ALB
Service oluştururken ALB’yi de bağlıyoruz. Trafiği task’lara bölen bu katmandır.
aws ecs create-service \
--cluster image-classifier-api-cluster \
--service-name image-classifier-api-service \
--task-definition image-classifier-api \
--desired-count 2 \
--launch-type FARGATE \
--load-balancers targetGroupArn=$TG_ARN,containerName=image-classifier-api,containerPort=8080
Security Group ayarı kritik: ALB’nin container’lara ulaşabilmesi için inbound kuralları doğru olmalı.
| Kaynak | Port | Açıklama |
|---|---|---|
0.0.0.0/0 |
80 | ALB’ye dışarıdan gelen trafik |
| ALB Security Group | 8080 | ALB’den container’a gelen trafik |
Ölçekleme
Service’i güncelleyerek anında yatay ölçekleme yapılabilir:
# 5 task'a çıkar
aws ecs update-service \
--cluster image-classifier-api-cluster \
--service image-classifier-api-service \
--desired-count 5
# Mevcut durumu kontrol et
aws ecs describe-services \
--cluster image-classifier-api-cluster \
--services image-classifier-api-service
ALB gelen istekleri mevcut task’lar arasında round-robin ile dağıtır. Yeni task’lar ayağa kalktıkça otomatik olarak ALB’nin hedef grubuna eklenir.
Canlı Test
ALB DNS alındıktan sonra:
curl -X POST http://ALB_DNS/predict -F "file=@gorsel.jpg"
Yanıt:
{
"result": true,
"skor": 0.94,
"s3_key": "uploads/..."
}
curl her seferinde farklı bir task’a gidebilir. CloudWatch Logs → Log Groups → task loglarını izleyerek hangi task’ın cevap verdiğini görebilirsin.
Maliyet ve Temizlik
Demo için tahmini maliyet:
| Kaynak | Birim maliyet |
|---|---|
| Fargate (1 vCPU, 2 GB) × 2 task | ~$0.10/saat |
| ALB | ~$0.02/saat |
| ECR (500 MB imaj) | ~$0.05/ay |
| Toplam | ~$0.12/saat |
3 saatlik demo ≈ $0.40. Bırakılırsa birikir — demodan sonra mutlaka silin:
# 1. Service'i durdur (desired count = 0)
aws ecs update-service \
--cluster image-classifier-api-cluster \
--service image-classifier-api-service \
--desired-count 0
# 2. Service sil
aws ecs delete-service \
--cluster image-classifier-api-cluster \
--service image-classifier-api-service
# 3. Cluster sil
aws ecs delete-cluster --cluster image-classifier-api-cluster
# 4. ECR repository sil
aws ecr delete-repository \
--repository-name image-classifier-api --force
Local vs AWS: Ne Değişti?
Local: docker run → localhost:8000
AWS: ECR push → ECS Task → ALB → public URL
Mimari aynı: bir container, bir port, bir API. Fark altyapıda: AWS artık yeniden başlatmayı, yük dağıtımını ve network yönetimini hallediyor. Container’ın içinden bakınca hiçbir şey değişmedi.