Bir container silindiğinde, içine yazılmış her şey de onunla birlikte gider — container’lar tasarım gereği geçicidir (ephemeral). Peki bir veritabanı container’ını yeniden başlattığınızda tüm verinizin kaybolmasını nasıl önlersiniz? Cevap: volume‘ler — container’ın yaşam döngüsünden bağımsız, kalıcı veri depolama alanları.

Container’lar neden geçicidir?

Bir container, imajın üzerine ince, yazılabilir bir katman (writable layer) ekleyerek çalışır. Container içinde yaptığınız her değişiklik (yeni dosya, log kaydı, veritabanı satırı) bu ince katmana yazılır. Container silindiğinde bu katman da siliniyor — imajın kendisi hiç değişmiyor. Bu, aynı imajdan defalarca temiz bir kopya başlatabilmenizi sağlayan tasarımın ta kendisi, ama kalıcı veri için ayrı bir mekanizma gerektirir.

Üç depolama seçeneği

Yöntem Nerede saklanır Ne zaman kullanılır
Named volume Docker’ın yönettiği alanda (/var/lib/docker/volumes/...) Veritabanları, kalıcı uygulama verisi — önerilen yöntem
Bind mount Host’ta sizin belirlediğiniz herhangi bir dizin Geliştirme sırasında kaynak kodu container’a canlı yansıtmak
tmpfs mount Sadece host’un belleğinde (RAM), diske hiç yazılmaz Geçici, hassas veriler (örn. şifreleme anahtarları)

Named volume: kalıcı veri için standart yol

# Bir volume oluştur (isteğe bağlı — run sırasında da otomatik oluşur)
docker volume create pg_data

# PostgreSQL container'ını bu volume'e bağla
docker run -d --name veritabani \
  -e POSTGRES_PASSWORD=gizli123 \
  -v pg_data:/var/lib/postgresql/data \
  postgres:16

# Container'ı sil, volume'ü SİLME
docker rm -f veritabani

# Aynı volume'e bağlı yeni bir container başlat — veri hâlâ orada!
docker run -d --name veritabani-v2 \
  -e POSTGRES_PASSWORD=gizli123 \
  -v pg_data:/var/lib/postgresql/data \
  postgres:16

Buradaki kritik nokta: docker rm ile container’ı sildiğinizde volume dokunulmadan kalır. Yeni bir container aynı volume adını referans ettiğinde, önceki tüm veriye sorunsuzca erişir.

✓

Volume’lerinizi yönetmek için: docker volume ls (listele), docker volume inspect pg_data (detayları gör), docker volume rm pg_data (sil — sadece hiçbir container kullanmıyorsa).

Bind mount: geliştirme sırasında canlı kod yansıtma

Geliştirme yaparken, kaynak kodunuzu her değişiklikte yeniden imaj build etmeden container içine anlık yansıtmak isteyebilirsiniz. Bunun için host’taki bir dizini doğrudan container’a bağlayan bind mount kullanılır:

# Host'taki ./src dizinini container içindeki /app/src'e bağla
docker run -d --name gelistirme \
  -v $(pwd)/src:/app/src \
  -p 3000:3000 \
  node:20-alpine npm run dev

Artık host’ta bir dosyayı düzenlediğinizde değişiklik anında container içinde de görünür — imajı yeniden build etmeye gerek kalmaz. Bind mount’un dezavantajı taşınabilirliktir: host’un dosya sistem yapısına bağımlı olduğu için, aynı komutu farklı bir makinede çalıştırdığınızda dizin yolunun orada da var olması gerekir.

Docker Compose’da volume tanımlamak

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: gizli123
    volumes:
      - pg_data:/var/lib/postgresql/data   # named volume

  web:
    build: .
    volumes:
      - ./src:/app/src                     # bind mount

volumes:
  pg_data:   # named volume'ü burada tanımlamak gerekir

Sık yapılan hata: yanlışlıkla volume silmek

Silme komutlarına dikkat: docker compose down -v, Compose dosyasındaki isimli volume’leri kalıcı olarak siler (düz docker compose down silmez). docker volume prune ve docker system prune --volumes Docker 29.4 denemesinde yalnızca anonim volume’leri temizledi; isimli volume, hiçbir container’a bağlı olmasa da yerinde kaldı. docker volume prune -a ise bağlı olmayan isimli volume’leri de siler. Production ortamında çalıştırmadan önce docker volume ls ile kontrol edin — geri dönüşü yoktur.

Verinizi kalıcı hale getirdikten sonra sıradaki doğal adım, birden fazla container’ın birbiriyle nasıl güvenli ve öngörülebilir şekilde haberleştiğidir — bunu bir sonraki yazıda, Docker networking başlığı altında ele alıyoruz.