FastAPI · MobileNetV2 · Docker Build & Run · Ölçekleme
docker build → docker run → testTarayıcıdan resim yükle → API tahmin döndürsün:
{
"dosya": "kedi.jpg",
"tahminler": [
{"sinif": "Egyptian Cat",
"guven": 87.3},
{"sinif": "Tabby",
"guven": 8.1}
]
}
| Web Framework | FastAPI |
| Server | Uvicorn |
| ML | TensorFlow CPU |
| Model | MobileNetV2 (ImageNet) |
| Image İşleme | Pillow |
| Base Image | python:3.11-slim |
image-classifier-api/ │ ├── app/ │ ├── __init__.py │ ├── main.py ← FastAPI app │ └── model.py ← ML tahmin │ ├── requirements.txt ├── Dockerfile ├── docker-compose.yml └── README.md
GET / — Hoş geldin sayfasıPOST /predict — Resim al, tahmin döndürGET /health — Servis sağlık kontrolüGET /docs — Swagger UI (otomatik)preprocess_input)from fastapi import FastAPI, UploadFile, File, HTTPException from PIL import Image import io from app.model import predict_image app = FastAPI(title="Görüntü Sınıflandırma API") @app.post("/predict") async def predict(file: UploadFile = File(...)): if not file.content_type.startswith("image/"): raise HTTPException(status_code=400, detail="Sadece resim dosyası kabul edilir") contents = await file.read() image = Image.open(io.BytesIO(contents)) tahminler = predict_image(image) return {"dosya": file.filename, "tahminler": tahminler} @app.get("/health") async def health(): return {"durum": "çalışıyor"}
/docs adresine gidince Swagger UI otomatik açılır. Frontend yazmadan API test edilebilir.
from tensorflow.keras.applications import MobileNetV2 from tensorflow.keras.applications.mobilenet_v2 import ( preprocess_input, decode_predictions ) import numpy as np _model = None # Singleton — bir kere yükle def _get_model(): global _model if _model is None: _model = MobileNetV2(weights="imagenet") return _model def predict_image(image, top_k=3): model = _get_model() img = image.convert("RGB").resize((224, 224)) arr = np.expand_dims(np.array(img, dtype=np.float32), axis=0) arr = preprocess_input(arr) preds = model.predict(arr, verbose=0) return [{"sinif": l, "guven": round(s*100,2)} for _,l,s in decode_predictions(preds,top_k)[0]]
FROM python:3.11-slim WORKDIR /app # Sistem paketleri (Pillow için) RUN apt-get update && apt-get install -y \ libglib2.0-0 libgl1-mesa-glx \ && rm -rf /var/lib/apt/lists/* # Önce bağımlılıklar (cache!) COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Model ağırlıklarını build'de indir RUN python -c "from tensorflow.keras.applications \ import MobileNetV2; MobileNetV2(weights='imagenet')" # Uygulama kodu (en sona — sık değişir) COPY app/ app/ EXPOSE 8000 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
apt-get — OS paketleri (hiç değişmez)COPY requirements → pip install — yavaş ama nadir değişirModel indirme — build'de bir kereCOPY app/ — hızlı, sık değişir → sona
docker build -t image-classifier:v1 . # İlk build: ~15-20 dk (TF indirme) # Sonraki build: ~30 saniye (cache) # Boyutu kontrol et docker images image-classifier
docker run -d \ -p 8000:8000 \ --name classifier \ image-classifier:v1 # Log takibi docker logs -f classifier # Tarayıcıda aç # http://localhost:8000/docs # Curl ile test curl -X POST http://localhost:8000/predict \ -F "[email protected]"
# Çalışan containerlar docker ps # Tüm containerlar (durmuş dahil) docker ps -a # Canlı CPU / RAM kullanımı docker stats classifier # Log takibi docker logs -f classifier
# Container içine gir docker exec -it classifier bash # İçeride ls /app # dosyaları gör python --version # Python'u doğrula exit # Tam metadata (IP, portlar, mount) docker inspect classifier
# Durdur docker stop classifier # Sil docker rm classifier # Tüm çalışanları durdur docker stop $(docker ps -q) # Tüm durmuşları sil docker rm $(docker ps -aq) # Kullanılmayan her şeyi temizle docker system prune
0.0.0.0:8000→8000/tcphttp://localhost:8000/health{
"dosya": "kedi.jpg",
"tahminler": [
{
"sinif": "Egyptian Cat",
"guven_yuzdesi": 87.34
},
{
"sinif": "Tabby",
"guven_yuzdesi": 8.12
},
{
"sinif": "Tiger Cat",
"guven_yuzdesi": 4.54
}
]
}
docker run -d -p 8001:8000 image-classifier:v1 docker run -d -p 8002:8000 image-classifier:v1 docker run -d -p 8003:8000 image-classifier:v1
docker runTek bir container'ı tek seferlik başlatırsın. Her parametre — port, env, volume, network — komut satırına yazılır. Tekrar çalıştırmak istersen aynı komutu hatırlamak zorundasın. İkinci bir container eklemek istersen ikinci bir komut daha.
docker compose
Tüm yapıyı bir YAML dosyasında tanımlarsın. Kim, hangi port,
hangi env, hangi volume, hangi sırayla ayağa kalkar — hepsi dosyada.
Sonra sadece docker compose up yazarsın.
| docker run | docker compose | |
|---|---|---|
| Tekrar kullanım | Komutu ezberle / kopyala | up yaz, bitti |
| Çoklu container | 3 ayrı komut | tek up |
| Ekip paylaşımı | "şu komutu çalıştır" | dosyayı git'e koy |
| Silme | her birini tek tek | down |
| Versiyonlama | yok | yml dosyası git'te |
services: api: build: . expose: - "8000" # ports değil expose nginx: image: nginx:alpine ports: - "80:80" depends_on: - api # 3 API instance: docker compose up --scale api=3 -d