Şimdiye kadar Dockerfile yazmayı, Compose ile çoklu servis yönetmeyi, volume’leri, networking’i, registry’i, CI/CD’yi ve izlemeyi tek tek gördük. Bu yazıda hepsini bir araya getirip, basit bir Node.js API’sini sıfırdan alıp gerçekçi bir production kurulumuna taşıyoruz — bu portaldaki tüm konuların birleştiği uçtan uca bir referans.
Proje: küçük bir görev listesi API’si
Node.js/Express ile yazılmış, PostgreSQL’e bağlanan basit bir REST API’miz olduğunu varsayalım. Klasör yapımız şöyle:
benim-api/
├── src/
│ └── server.js
├── package.json
├── Dockerfile
├── .dockerignore
└── docker-compose.yml
1. Adım: Multi-stage, güvenli bir Dockerfile
Önceki yazılarda gördüğümüz iyi pratikleri (küçük taban imaj, root olmayan kullanıcı, sabit sürüm etiketi, health check) tek bir Dockerfile’da birleştiriyoruz:
FROM node:20.15.1-alpine3.20 AS base
WORKDIR /app
COPY package*.json ./
FROM base AS deps
RUN npm ci --production
FROM base AS runtime
COPY --from=deps /app/node_modules ./node_modules
COPY src/ ./src
RUN addgroup -S uygulama && adduser -S uygulama -G uygulama
USER uygulama
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -q -O- http://localhost:3000/saglik || exit 1
CMD ["node", "src/server.js"]
# .dockerignore
node_modules
.git
.env
*.log
2. Adım: Compose ile API + veritabanı + reverse proxy
Volume’ler kalıcı veriyi, servis isimleri (network) container’lar arası iletişimi, depends_on başlatma sırasını yönetir:
services:
api:
build: .
environment:
DB_HOST: db
DB_PASSWORD: ${DB_PASSWORD}
depends_on:
- db
restart: unless-stopped
db:
image: postgres:16.3-alpine
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pg_data:/var/lib/postgresql/data
restart: unless-stopped
proxy:
image: nginx:1.27-alpine
ports:
- "443:443"
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- api
restart: unless-stopped
volumes:
pg_data:
Veritabanı portu (5432) dışarıya hiç açılmıyor — sadece api servisi, aynı Compose ağı üzerinden db ismiyle erişebiliyor. Dışarıdan gelen tüm trafik proxy (Nginx) üzerinden geçiyor; bu hem TLS sonlandırmayı tek yerde toplar hem de API’yi doğrudan internete açmaz.
Şifreler ve gizli değerler (DB_PASSWORD) doğrudan docker-compose.yml‘a yazılmadı — bir .env dosyasından okunuyor (${DB_PASSWORD}). .env dosyasını .gitignore‘a eklemeyi unutmayın.
3. Adım: CI/CD ile otomatik build, tarama ve push
Önceki “CI/CD ile Docker” yazımızdaki pipeline’ı bu projeye uygularsak: kod main‘e push edilince imaj build edilir → Trivy ile taranır → geçerse çok mimarili (amd64 + arm64) olarak registry’e gönderilir → sunucuda otomatik çekilip devreye alınır. Tüm bu adımlar tek bir .github/workflows/deploy.yml dosyasında birleşir; her adımın detayını ilgili yazılarımızda bulabilirsiniz.
4. Adım: Sunucuda devreye alma
# Sunucuda ilk kurulum
git clone https://github.com/kullanici-adi/benim-api.git
cd benim-api
echo "DB_PASSWORD=guclu-bir-parola" > .env
docker compose up -d
# CI/CD her yeni sürümde bu adımı otomatik çalıştırır
docker compose pull
docker compose up -d --no-deps --build api
5. Adım: Sağlığı ve kaynak kullanımını izleme
# Hızlı, tek sunuculuk kontrol
docker compose ps # health check durumları burada görünür
docker stats
docker compose logs -f api
Trafik büyüdükçe, “Container İzleme ve Loglama” yazımızda anlattığımız cAdvisor + Prometheus + Grafana üçlüsünü aynı docker-compose.yml‘a birer servis olarak eklemek, tek komutla (docker compose up -d) tüm izleme yığınını da ayağa kaldırır.
Tüm parçaların birbirine bağlandığı yer
| İhtiyaç | Kullanılan araç/kavram |
|---|---|
| Küçük, güvenli imaj | Multi-stage Dockerfile, alpine taban imaj, USER, HEALTHCHECK |
| Kalıcı veri | Named volume (pg_data) |
| Servisler arası iletişim | Compose’un otomatik oluşturduğu ağ, servis ismiyle DNS |
| Dış dünyaya güvenli erişim | Nginx reverse proxy, sadece 80/443 dışarı açık |
| İmaj dağıtımı | GitHub Container Registry / Docker Hub |
| Otomasyon | GitHub Actions: build → tara → push → deploy |
| Çoklu donanım desteği | Buildx ile linux/amd64,linux/arm64 |
| Sağlık ve gözlemlenebilirlik | HEALTHCHECK, docker stats, Prometheus + Grafana |
Bu portaldaki her yazı, burada bir araya gelen parçalardan birini derinlemesine ele alıyor. Kendi projeniz için bu şablonu başlangıç noktası olarak kullanabilir, ihtiyacınıza göre (Kubernetes’e geçiş, çoklu bölge dağıtımı, otomatik ölçekleme gibi) üzerine katman katman ekleyebilirsiniz.