Teknoloji

Küçük SaaS Uygulamaları İçin Docker Compose ile Production VPS Mimarisi

Neden Küçük SaaS Projeleri İçin Docker Compose + Tek VPS İkilisi Çok Mantıklı?

Küçük ama gelir üreten bir SaaS uygulaması geliştiriyorsanız, ilk büyük mimari kararlardan biri altyapı tarafında geliyor: paylaşımlı hosting yetersiz, Kubernetes fazla ağır, çıplak VPS ise manuel ayarlarla zaman yediriyor. Tam bu noktada Docker Compose + tek VPS yaklaşımı, sade ama üretim için yeterince güçlü bir orta yol sunuyor.

Bu yazıda DCHost ekibi olarak, küçük SaaS ve API projelerinde sık kullandığımız, pratikte defalarca test ettiğimiz bir üretim mimarisini detaylandıracağız: Docker Compose ile tek VPS üzerinde reverse proxy, otomatik SSL ve sağlam bir yedekleme stratejisi. Amaç; hem geliştirici dostu, hem de uykunuzu kaçırmayacak kadar güvenli ve tekrar üretilebilir bir yapı kurmak.

Eğer henüz Docker ile VPS tarafında çok haşır neşir değilseniz, önce Docker ile VPS’te izole uygulama barındırma rehberimize göz atmanız faydalı olabilir. Bu yazıda ise doğrudan production odaklı ilerleyeceğiz: domain yönlendirmesi, HTTPS, .env yönetimi, veri saklama ve uzak yedeğe kadar tabloyu uçtan uca netleştireceğiz.

Tek VPS + Docker Compose Mimarisi Ne Zaman Doğru Seçim?

Küçük SaaS’ler için altyapı tasarlarken kritik soru şudur: “Şu an neye gerçekten ihtiyacım var ve 1–2 yıl içinde bu yapıyı nereye evireceğim?” Fazla karmaşık bir mimari, küçük ekiplere gereksiz operasyonel yük bindirir; fazla basit yapı ise büyümede tıkanır.

Bu mimarinin güçlü olduğu senaryolar

  • Tek ürün veya birkaç küçük mikro ürün: Örneğin tek tenant’lı ya da basit multi-tenant bir SaaS panosu.
  • Aylık orta düzey trafik: Yüzlerce – birkaç bin aktif kullanıcı, orta düzey API trafiği.
  • Küçük ekipler: 1–5 kişilik ürün ekipleri, ayrı bir DevOps takımı olmayan yapılar.
  • Hızlı MVP → üretim geçişi: MVP’yi çok bozmadan, biraz sertleştirerek production’a almak isteyenler.

Artıları

  • Basitlik: Tüm servisler tek VPS üzerinde, tek Docker Compose dosyasıyla yönetilir.
  • Taşınabilirlik: İhtiyaç halinde başka bir DCHost VPS’ine taşıma; Compose dosyası sayesinde oldukça kolaydır.
  • Şeffaf maliyet: CPU, RAM, disk ve trafik tüketimini net görürsünüz; büyüdükçe planlı yükseltebilirsiniz.
  • GitOps’a yakın yapı: Konfigürasyonun büyük bölümü kodla yönetildiği için versiyonlanabilir.

Sınırları ve büyüme yolu

Bu modelin sınırlarını bilmek de önemli:

  • Yük çok arttığında veritabanını ayrı VPS’e ayırma ihtiyacı doğar.
  • Gerçek yüksek erişilebilirlik (HA) için tek VPS yeterli değildir; çoklu VPS ve replikasyon gerekir.
  • Ağır arka plan iş yükleri (queue, raporlama, video işleme vb.) için ek worker VPS’leri mantıklı hale gelir.

Bu noktada, küçük SaaS uygulamaları için tek VPS, çoklu VPS ve yönetilen bulut mimarilerini karşılaştırdığımız rehbere de mutlaka göz atmanızı öneririz. Burada anlattığımız Compose mimarisi, o yol haritasının ilk, en pratik basamağıdır.

Production İçin Temel Bileşenler: Hangi Servisler Olmalı?

Sağlam bir Compose tabanlı üretim mimarisinde genelde şu bileşenler bulunur:

  • Reverse proxy: Nginx veya Traefik ile domain yönlendirme, SSL terminasyonu.
  • Uygulama servisi: Laravel, Node.js, Django, Go veya benzeri backend konteyneri.
  • Veritabanı: PostgreSQL veya MySQL/MariaDB.
  • Önbellek ve queue: Redis (isteğe bağlı, ama çoğu SaaS’te çok işe yarıyor).
  • Arka plan işçileri: Queue worker, cron job’ları.
  • Yedekleme servisi: Veritabanı ve volume yedeklerini alan hafif bir container ya da host tarafı cron.

Örnek klasör yapısı

/srv/saas-app/
  docker-compose.yml
  docker-compose.override.yml (opsiyonel)
  .env
  nginx/
    default.conf
  app/
    Dockerfile
    src/ (uygulama kodu)
  backup/
    backup.sh

Bu yapı sayesinde hem uygulama kodu hem de altyapı tanımı tek bir repo veya dizin altında toplanır; yeni bir DCHost VPS’ine geçtiğinizde, büyük oranda şu üç adımla ayağa kalkabilirsiniz: kodu çek, .env’i doldur, docker compose up -d.

Örnek Docker Compose Dosyası: Parça Parça İnceleyelim

Aşağıdaki yapı taşları, sade ama production’a oldukça yakın bir iskelet sunuyor. Kendi teknoloji yığınınıza göre imaj isimlerini ve environment değişkenlerini uyarlayabilirsiniz.

Temel Compose iskeleti

version: '3.9'

services:
  reverse-proxy:
    image: nginx:stable-alpine
    container_name: saas_reverse_proxy
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
      - certs:/etc/letsencrypt
      - certs-data:/var/lib/letsencrypt
    ports:
      - '80:80'
      - '443:443'
    depends_on:
      - app
    networks:
      - web

  app:
    build: ./app
    container_name: saas_app
    env_file:
      - .env
    depends_on:
      - db
      - redis
    networks:
      - web
      - internal

  db:
    image: postgres:16-alpine
    container_name: saas_db
    environment:
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - internal

  redis:
    image: redis:7-alpine
    container_name: saas_redis
    command: ['redis-server', '--appendonly', 'yes']
    volumes:
      - redis-data:/data
    networks:
      - internal

  backup:
    build: ./backup
    container_name: saas_backup
    env_file:
      - .env
    volumes:
      - db-data:/var/lib/postgresql/data:ro
      - backup-data:/backups
    networks:
      - internal
    restart: unless-stopped

networks:
  web:
  internal:

volumes:
  db-data:
  redis-data:
  certs:
  certs-data:
  backup-data:

Bu dosyada dikkat edilmesi gereken kritik noktalar:

  • İki ayrı network: web dışa açık reverse proxy’nin konuştuğu ağ; internal ise veritabanı ve Redis gibi iç servisler için.
  • Named volume kullanımı: Veritabanı, Redis, sertifikalar ve yedekler için ayrı volume’ler tanımlanmış durumda.
  • backup servisi: Host tarafında cron da kullanılabilir; burada her şeyi Compose ile yönetmek isteyen ekipler için örnek bir pattern gösteriyoruz.

Reverse Proxy ve SSL Otomasyonu: Nginx ile Üretim Hazır HTTPS

Docker Compose mimarisinde genelde iki popüler yol görürsünüz: Nginx tabanlı bir reverse proxy + Let’s Encrypt entegrasyonu veya Traefik/Caddy gibi kendinden ACME destekli çözümler. DCHost tarafında küçük SaaS’lerde sıkça Nginx + Let’s Encrypt ikilisini tercih ediyoruz; hem davranışı net, hem de gerektiğinde klasik Nginx konfigürasyon bilgisinden faydalanabiliyorsunuz.

Basit Nginx reverse proxy konfigürasyonu

Örnek bir nginx/default.conf dosyası şöyle olabilir:

server {
    listen 80;
    server_name app.ornek-saas.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    server_name app.ornek-saas.com;

    ssl_certificate     /etc/letsencrypt/live/app.ornek-saas.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.ornek-saas.com/privkey.pem;

    # Temel modern TLS ayarları (TLS 1.2+ ve güçlü şifre kümeleri)

    location / {
        proxy_pass http://saas_app:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}

Burada:

  • HTTP → HTTPS yönlendirme ile tüm trafiği güvenli katmana zorluyoruz.
  • proxy_pass ile app servisine (iç ağda çalışan) istekleri iletiyoruz.
  • ACME challenge için /.well-known/acme-challenge/ path’ini ayırdık; Certbot bu dizini kullanacak.

Let’s Encrypt ile otomatik SSL sertifikası

SSL sertifikalarını manuel yenilemek production’da sürdürülemez. Bu yüzden Let’s Encrypt + Certbot veya acme.sh gibi araçlarla otomatik yenileme kritik önem taşıyor. DCHost blogunda SSL sertifika otomasyonu ve ACME stratejilerini detaylandırdık; burada Compose senaryosuna uyarlayalım.

Tipik yaklaşım:

  1. Nginx içinde HTTP portu üzerinden ACME challenge yanıtlanır.
  2. Host tarafında çalışan bir Certbot cron job’ı, sertifikaları yeniler ve ilgili volume’e yazar.
  3. Volume, reverse proxy konteynerine mount edilmiştir; Nginx sertifikaları doğrudan bu volume’den okur.

Basit bir host cron girdisi örneği:

0 3 * * * docker run --rm 
  -v certs:/etc/letsencrypt 
  -v certs-data:/var/lib/letsencrypt 
  certbot/certbot renew --webroot -w /var/www/certbot 
  && docker exec saas_reverse_proxy nginx -s reload

Böylece her gece saat 03:00’te sertifikalar yenilenir, Nginx reload edilir ve hiçbir kesinti yaşamadan HTTPS güncel kalır.

.env, Gizli Anahtarlar ve Konfigürasyon Yönetimi

Docker Compose mimarisinde en sık yapılan hatalardan biri; gizli anahtarları doğrudan docker-compose.yml içine gömmek veya repoya .env dosyasını da dahil etmektir. Production ortamında gizli anahtar yönetimi çok daha dikkatli ele alınmalı.

.env dosyası için temel prensipler

  • .env hiçbir zaman VCS’e (Git) commit edilmemeli.
  • Her ortam (staging, prod) için ayrı .env dosyanız olmalı.
  • DB parolaları, API anahtarları, JWT secret, encryption key gibi değerler yalnızca .env içinde tutulmalı.

Bu konuya daha derinlemesine girmek isterseniz, VPS’te .env ve gizli anahtar yönetimi rehberimizde ortam değişkeni, şifreleme ve rotasyon pratiklerini adım adım anlattık.

config-as-code yaklaşımı

.env dosyası hariç tüm Compose ve Nginx yapılandırmalarını Git ile takip etmek, hem geri dönüşü hem de yeni sunucuya taşımayı inanılmaz kolaylaştırır. Önerimiz:

  • docker-compose.yml, Nginx konfigleri, backup script’leri, hatta sistemd unit dosyalarınız tek bir repoda olsun.
  • Sunucuya dağıtımı isterseniz Git pull ile, isterseniz CI/CD pipeline’ı ile yapın.

DCHost blogunda GitHub Actions ile VPS’e otomatik deploy ve sıfır kesinti yayın mimarisini de anlattık; Compose tabanlı bu yapıyı oradaki stratejilerle kolayca birleştirebilirsiniz.

Veri ve Yedekleme: Sadece Volume Tutmak Yedek Değildir

Docker volume’leri veriyi saklar ama yedek değildir. Sunucu tarafında disk arızası, yanlışlıkla volume silinmesi veya uygulama hataları sizi saniyeler içinde tüm müşteri verisini kaybetme noktasına getirebilir. Küçük SaaS projelerinde de profesyonel yedekleme standartlarına uymak zorundasınız.

Ne yedeklemelisiniz?

  • Veritabanı dump’ı: PostgreSQL için pg_dump, MySQL/MariaDB için mysqldump veya XtraBackup.
  • Uygulama dosyaları: Kullanıcı yüklemeleri (uploads), statik medya, rapor dosyaları vb.
  • Konfigürasyon: docker-compose.yml, Nginx konfigleri, .env’in şifreli bir kopyası.

3-2-1 yedekleme kuralını SaaS’e uyarlamak

Klasik 3-2-1 kuralı:

  • 3 kopya (1 üretim, 2 yedek),
  • 2 farklı ortam (örneğin disk + object storage),
  • 1 tanesi farklı lokasyonda (farklı veri merkezi veya offsite).

Bunu Compose tabanlı küçük SaaS’te şöyle uygulayabilirsiniz:

  1. Günlük veritabanı dump’ı + uploads klasörü, VPS içinde ayrı bir volume’e alınır.
  2. Her gece bu volume, object storage’a (S3 uyumlu) veya başka bir DCHost VPS’ine senkronize edilir.
  3. Haftalık/aylık arşivler uzun süreli saklama için tutulur.

3-2-1 kuralını detaylandırdığımız 3-2-1 yedekleme stratejisi rehberinde de, VPS ortamına özel pratik öneriler bulabilirsiniz.

Basit backup konteyneri örneği

Örneğin PostgreSQL kullanan küçük bir SaaS’te, her gece çalışan bir backup script’i şöyle görünebilir:

#!/bin/sh
set -e

DATE=$(date +"%Y-%m-%d_%H-%M")
BACKUP_DIR=/backups

pg_dump -h saas_db -U "$DB_USER" "$DB_NAME" 
  | gzip > "$BACKUP_DIR/db_${DATE}.sql.gz"

# Eski yedekleri 14 günden sonra sil
find "$BACKUP_DIR" -type f -mtime +14 -delete

Bu script’i backup konteynerinizin içine koyabilir, container içinde cron ile tetikleyebilir veya host tarafında docker exec saas_backup /backup/backup.sh komutunu cron’dan çağırabilirsiniz.

Uzak yedeğe senkronizasyon

Yedekleri VPS içinde tutmak tek başına yeterli değildir. Çok basit bir senaryoda bile rsync veya rclone ile yedek klasörünü object storage’a ya da farklı bir DCHost VPS’ine kopyalayabilirsiniz. Gelişmiş senaryolar için Restic ve Borg ile S3 uyumlu uzak yedekleme rehberimizde sürümleme, şifreleme ve saklama politikalarını adım adım anlattık.

Güncelleme, Ölçeklendirme ve Operasyonel Pratikler

Production ortamda Compose kullanırken sadece “çalışıyor mu?” değil, “güncelleme yaparken kesinti olacak mı, logları nasıl takip edeceğim, ölçeklendirme sinyallerini nasıl okuyacağım?” sorularına da net cevap vermeniz gerekir.

Uygulamayı güncellerken kesintiyi azaltmak

  • Immutuable imaj yaklaşımı: Her sürüm için farklı tag kullanın (örnek: my-saas:1.3.0). Böylece rollback çok daha temiz olur.
  • healthcheck kullanın: Compose içinde healthcheck tanımlayarak container sağlıklı olmadan trafiği yönlendirmeyin.
  • Rolling benzeri yaklaşım: Küçük SaaS’lerde çoğu zaman kısa bir yeniden başlatma kabul edilebilir; ama veritabanı migrasyonlarını önce, kodu sonra güncellemek gibi basit stratejilerle kesintiyi saniyelere indirebilirsiniz.

Loglama ve izleme

İlk aşamada Docker’ın kendi log sistemi iş görebilir:

  • docker logs -f saas_app ile canlı log takibi,
  • docker compose logs --tail=200 ile son loglara bakma.

Biraz büyüdüğünüzde merkezi loglama (örneğin Grafana Loki + Promtail) ve metrik izleme (Prometheus + Grafana) görmek isteyeceksiniz. Bunun için VPS kaynak kullanımı izleme rehberimiz iyi bir başlangıç noktası olabilir.

Kaynak planlama ve dikey/çapraz ölçeklendirme

Tek VPS + Compose modelinde ilk ölçeklendirme adımı çoğunlukla dikey ölçeklemedir: DCHost üzerindeki VPS planınızı daha fazla vCPU, RAM veya NVMe disk içerecek şekilde yükseltmek. Yine de, mimariyi kurarken şunları aklınızda tutun:

  • Veritabanı ile uygulamayı ağ üzerinden konuşan ayrı servisler olarak tasarladığınız için, ileride veritabanını ayrı bir VPS’e taşımak görece kolay olur.
  • Queue ve arka plan işlerini ayrı bir container’a koyarsanız, yoğun dönemlerde bu container’ı çoğaltmak (scale) daha kolaydır.
  • Reverse proxy’yi hafif tutar, mümkün olduğunca statik dosyaları CDN’e aktarırsanız, tek VPS uzun süre iş görür.

DCHost Üzerinde Bu Mimarinin Pratik Avantajları

DCHost olarak NVMe diskli, hızlı ağ bağlantılı ve Türkiye/Avrupa lokasyon seçenekli VPS altyapımızı özellikle küçük ve orta ölçekli SaaS projeleri düşünülerek tasarlıyoruz. Compose tabanlı bu mimariyi DCHost üzerinde kurduğunuzda:

  • Yük arttığında CPU/RAM yükseltmeyi minimum kesinti ile yapabilirsiniz.
  • Gerektiğinde aynı veri merkezinde ikinci bir VPS açıp veritabanını ayırarak bir üst seviyeye geçebilirsiniz.
  • Yedekleri aynı bölgede ya da farklı bölgede tutarak felaket senaryolarına karşı koruma sağlayabilirsiniz.

Altyapı tarafında ilk kurulumu kendiniz yapmak istemezseniz, Compose dosyalarınızı ve gereksinimlerinizi bizimle paylaşıp, DCHost ekibiyle birlikte mimariyi gözden geçirerek üretim ortamınızı çok daha sağlam şekilde ayağa kaldırabilirsiniz.

Sonuç: Küçük SaaS İçin Fazla Karmaşaya Girmeden Üretim Hazır Mimari

Küçük SaaS projeleri için asıl hedef; müşteri değerini hızlı üretirken altyapıyı da ölçeklenebilir, tekrar üretilebilir ve güvenli tutmaktır. Tek VPS üzerinde Docker Compose ile kurduğumuz mimari tam da bu dengeyi yakalar: Reverse proxy ile domain ve HTTPS yönetimi, Compose servisleriyle uygulama/veritabanı/Redis izolasyonu, otomatik SSL ve 3-2-1 uyumlu yedekleme stratejisi ile beklenmedik sorunlara karşı koruma.

Buradan sonra atabileceğiniz adımlar net:

  • Mevcut veya yeni DCHost VPS’inizde bu yazıdaki klasör ve Compose iskeletini kurun.
  • .env, Nginx ve backup script’lerini kendi SaaS’inize göre uyarlayın.
  • Yedeklerin gerçekten çalıştığını görmek için en az bir kez geri yükleme testi yapın.

Eğer “Uygulamam büyürse bu setup nerelere kadar taşır, ne zaman ikinci VPS’e geçmeliyim, ne zaman veritabanını ayırmalıyım?” gibi sorularınız varsa, küçük SaaS’ler için hosting mimarisi rehberimizde bu yol haritasını detaylandırdık. Projenizin gereksinimlerine özel değerlendirme yapmak isterseniz, DCHost ekibiyle iletişime geçerek VPS seçenekleri, yedekleme topolojisi ve güvenlik sertleştirme adımlarını birlikte netleştirebiliriz.

Doğru kurgulanmış bir Docker Compose + VPS mimarisiyle, altyapı yangınlarıyla uğraşmak yerine enerjinizi ürününüzü büyütmeye ayırabilirsiniz. Geri kalanını DCHost altyapısına ve iyi tasarlanmış otomasyonlara bırakın.

Sıkça Sorulan Sorular

Genelde tek VPS + Docker Compose mimarisi; aylık trafiği orta düzeyde olan, tek ürün veya birkaç küçük servisten oluşan SaaS projeleri için uzun süre yeterli olur. CPU ve RAM kullanımı dengeliyse, veritabanı sorguları makul sürede dönüyorsa ve disk I/O tıkanmıyorsa dikey ölçekleme (VPS paketini büyütme) ile birkaç yıl gidebilirsiniz. Kritik eşik noktaları; veritabanı boyutunun hızla artması, yoğun queue/raporlama işlerinin CPU’yu sürekli zorlaması ve uptime beklentisinin “dakika” değil “saniye” hassasiyetine inmesidir. Bu sinyaller geldiğinde veritabanını ayrı VPS’e taşımak veya uygulama/worker’ları ikinci bir VPS’e bölmek mantıklı hale gelir.

Evet, doğru kurgulandığında Docker Compose ile Let’s Encrypt tabanlı otomatik SSL yenileme hem güvenli hem de operasyonel açıdan tavsiye edilen bir pratiktir. Dikkat etmeniz gereken noktalar; ACME challenge için yalnızca gerekli path’i (/.well-known/acme-challenge/) açmak, sertifika ve private key dosyalarını ayrı bir volume’de tutmak, bu volume’e sadece reverse proxy konteynerinin okuma izniyle erişmesini sağlamak ve yenileme sonrası Nginx/Traefik gibi bileşenleri kontrollü şekilde reload etmektir. Ayrıca, staging ortamında önce test ederek oran limitlerine takılmaktan kaçınmanız ve sertifika süresi dolmadan önce izleme/uyarı mekanizması kurmanız iyi bir güvenlik pratiğidir.

Evet, volume’ler veriyi saklasa da, veritabanı dump’ı almak farklı risk türlerine karşı ek bir güvenlik katmanı sağlar. Volume, disk arızası, yanlış silme, bozulmuş veri dosyaları veya fidye yazılıma karşı tek başına yeterli değildir. Dump’lar ise belirli bir anın mantıksal kopyasını tuttuğu için, uygulama hatalarıyla veritabanı yapısı bozulduğunda dahi geri dönmenize imkân tanır. İyi bir strateji; hem volume’ü (örneğin uploads klasörü gibi dosya verilerini) hem de düzenli veritabanı dump’larını yedeklemek ve bu ikisini 3-2-1 kuralına uygun şekilde farklı lokasyonda saklamaktır. Böylece hem fiziksel hem de mantıksal veri kaybı riskini ciddi oranda azaltmış olursunuz.

.env dosyasını hiçbir zaman versiyon kontrol sistemine eklememek ilk adımdır. Her ortam için ayrı .env dosyası bulundurmalı, bu dosyayı sadece yetkili kişilerin erişebildiği, SSH ile güvenli bağlantı kurulan sunucularda tutmalısınız. Daha ileri seviye için .env içeriğini şifreleyip (örneğin age/sops gibi araçlarla) repoda şifreli haliyle saklayıp, sadece deploy sırasında çözmek de mümkündür. Ayrıca, gizli anahtarları düzenli aralıklarla döndürmek (rotasyon), üretim sunucusunda “history” gibi kabuk kayıtlarında parola bırakmamak ve yedeklerde .env’i sadece şifreli şekilde tutmak önemlidir. Detaylı pratikler için DCHost’un VPS’te .env ve gizli anahtar yönetimi rehberindeki adımları takip edebilirsiniz.

Hayır, küçük ve orta ölçekli birçok SaaS projesi için iyi tasarlanmış bir Docker Compose + çoklu VPS mimarisi uzun yıllar boyunca yeterli olabilir. Kubernetes’e ihtiyaç genellikle; ekipte ayrı bir SRE/DevOps kapasitesi oluştuğunda, onlarca mikroservis ve çok bölgeye yayılmış altyapı söz konusu olduğunda veya otomatik ölçekleme/gelişmiş servis keşfi gibi özellikler kritik hale geldiğinde ortaya çıkar. Başlangıçta Compose ile servisleri, ağları ve bağımlılıkları temiz bir şekilde ayırmanız, ileride ister Kubernetes’e ister daha klasik çoklu VPS mimarisine geçerken size büyük avantaj sağlar. Yani Compose ile başlamak, ileride seçeneklerinizi kısıtlamaz; aksine daha kontrollü büyüme imkânı sunar.