Docker ile Ortam Kurulumu: Yazılım Geliştirmede Devrim Yaratan Yaklaşım
Yazılım geliştirme dünyasında en sık duyduğumuz cümlelerden biri şudur: "Ama benim makinemde çalışıyordu!" İşte Docker, tam da bu cümlenin tarihe karışması için doğdu. Bir uygulamayı geliştirdiğiniz ortamdan, test ortamına ve oradan da üretim ortamına taşırken yaşanan "bağımlılık cehennemi" sorunlarını kökten çözen Docker, modern yazılım geliştirme süreçlerinin vazgeçilmez bir parçası haline geldi.
Bu rehberde Docker'ın ne olduğundan başlayarak, gerçek dünya senaryolarında nasıl kullanılacağına kadar kapsamlı bir yolculuğa çıkacağız. İster yeni başlayan bir geliştirici olun, ister deneyimli bir DevOps mühendisi, bu yazıda size hitap eden bölümler bulacaksınız.
Docker Nedir ve Neden Bu Kadar Popüler?
Docker, uygulamalarınızı konteyner adı verilen izole ortamlarda paketlemenizi, dağıtmanızı ve çalıştırmanızı sağlayan açık kaynaklı bir platformdur. Geleneksel sanal makinelerden farklı olarak Docker, işletim sistemi çekirdeğini paylaşır ve yalnızca uygulamanın ihtiyaç duyduğu kütüphaneleri, bağımlılıkları ve yapılandırmaları paketler.
Bu yaklaşımın getirdiği avantajlar saymakla bitmez:
- Hafiflik: Sanal makineler gigabaytlarca yer kaplarken, konteynerler megabayt seviyesinde kalabilir.
- Hız: Saniyeler içinde ayağa kalkabilen konteynerler, dakikalar süren VM başlatma süreçlerini geride bırakır.
- Tutarlılık: Geliştirme, test ve üretim ortamları arasında "benim makinemde çalışıyordu" sorunu ortadan kalkar.
- Taşınabilirlik: Aynı imaj, Linux, Windows veya macOS üzerinde sorunsuz çalışır.
- Ölçeklenebilirlik: Kubernetes gibi orkestrasyon araçlarıyla binlerce konteyner yönetilebilir.
Docker'ın bu kadar yaygınlaşmasının temel sebebi, yazılım geliştirme yaşam döngüsünün her aşamasında tutarlılık ve tekrarlanabilirlik sağlamasıdır. Artık bir projeye katkıda bulunmak için "şu sürüm Python'u kur, şu kütüphaneyi yükle, şu ortam değişkenini ayarla" gibi onlarca adımı takip etmek zorunda değilsiniz. Tek bir komutla her şey hazır.
Temel Kavramlar: Docker Ekosistemini Anlamak
Docker'a dalmadan önce terminolojiye hâkim olmak, sonraki konuları çok daha rahat anlamanızı sağlar.
İmaj (Image)
İmaj, bir konteynerin oluşturulması için gereken her şeyi içeren salt okunur bir şablondur. İşletim sistemi katmanı, uygulama kodu, kütüphaneler ve yapılandırma dosyaları bu imajın içinde yer alır. Docker Hub üzerinden hazır imajlar çekebileceğiniz gibi, kendi imajlarınızı da oluşturabilirsiniz.
Konteyner (Container)
Konteyner, bir imajın çalışan örneğidir. İmaj bir sınıf tanımıysa, konteyner o sınıftan üretilmiş bir nesnedir diyebiliriz. Konteynerler izole edilmiş dosya sistemlerine, ağlara ve süreç alanlarına sahiptir.
Dockerfile
Dockerfile, kendi imajınızı nasıl oluşturacağınızı tanımlayan metin dosyasıdır. Her satırı bir talimat içerir ve bu talimatlar sırayla işlenerek katmanlı bir imaj oluşturulur.
Volume (Birim)
Volume'lar, konteynerlerin kalıcı veri saklamasını sağlar. Konteyner silinse bile volume içindeki veriler korunur. Veritabanları, log dosyaları ve kullanıcı verileri için hayati önem taşır.
Network (Ağ)
Docker, konteynerler arasında iletişimi sağlamak için çeşitli ağ sürücüleri sunar. Bridge, host, overlay ve macvlan en yaygın kullanılanlardır.
Docker Kurulumu: İşletim Sistemine Göre Adımlar
Docker'ı kurmak, işletim sisteminize bağlı olarak birkaç dakika sürer.
Linux (Ubuntu/Debian)
Resmi depodan kurulum yapmak en sağlıklı yöntemdir:
sudo apt update
sudo apt install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Kurulumdan sonra Docker servisini başlatıp, kullanıcınızı docker grubuna ekleyerek sudo olmadan kullanabilirsiniz:
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
macOS ve Windows
Her iki platform için de Docker Desktop en pratik çözümdür. macOS'ta Apple Silicon ve Intel çipleri için ayrı sürümler bulunur. Windows'ta ise WSL2 altyapısı üzerinde çalışır ve bu sayede Linux konteynerlerini sorunsuz çalıştırabilirsiniz.
Kurulumun başarılı olduğunu doğrulamak için:
docker --version
docker run hello-world
İlk Dockerfile'ınızı Yazmak
Teorik bilgiyi pratiğe dökelim. Basit bir Node.js uygulaması için Dockerfile yazalım:
# Temel imajı belirliyoruz
FROM node:20-alpine
# Çalışma dizinini ayarlıyoruz
WORKDIR /app
# Bağımlılık dosyalarını kopyalıyoruz
COPY package*.json ./
# Bağımlılıkları yüklüyoruz
RUN npm ci --only=production
# Uygulama kodunu kopyalıyoruz
COPY . .
# Uygulamanın dinleyeceği portu belirtiyoruz
EXPOSE 3000
# Konteyner başladığında çalışacak komut
CMD ["node", "server.js"]
Bu Dockerfile'daki her talimatın bir amacı var:
FROM, hangi temel imajdan başlayacağımızı söyler.alpinesürümü minimal boyutuyla öne çıkar.WORKDIR, sonraki komutların çalışacağı dizini belirler.COPY, dosyaları host makineden imaja kopyalar.RUN, imaj oluşturulurken çalışacak komutları tanımlar.EXPOSE, hangi portun dışarıya açılacağını belgeler.CMD, konteyner her başladığında çalışacak varsayılan komuttur.
İmajı oluşturmak ve çalıştırmak için:
docker build -t my-app:1.0 .
docker run -p 3000:3000 my-app:1.0
Docker Compose ile Çoklu Konteyner Yönetimi
Gerçek dünya uygulamaları genellikle tek bir konteynerden ibaret değildir. Bir web uygulaması, veritabanı, önbellek katmanı ve mesaj kuyruğu bir arada çalışır. Docker Compose, bu karmaşıklığı tek bir YAML dosyasıyla yönetmenizi sağlar.
version: '3.9'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
- REDIS_URL=redis://cache:6379
depends_on:
- db
- cache
volumes:
- ./src:/app/src
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
cache:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
postgres_data:
Bu dosyayı docker-compose.yml olarak kaydettikten sonra tüm sistemi tek komutla ayağa kaldırabilirsiniz:
docker compose up -d
docker compose logs -f web
docker compose down
Geliştirme Ortamında Docker Kullanmanın Avantajları
Docker'ı yalnızca üretim ortamı için düşünmek büyük bir yanılgıdır. Geliştirme sürecinde de sayısız fayda sağlar:
Tutarlı Geliştirme Ortamı
Ekip üyelerinin farklı işletim sistemleri kullanması artık sorun değildir. Herkes aynı imajı çalıştırdığı için "senin Node sürümün farklı" gibi tartışmalar son bulur.
Hızlı Onboarding
Yeni bir geliştirici ekibe katıldığında, tüm geliştirme ortamını kurmak için tek bir komut yeterlidir. Saatler süren kurulum süreçleri dakikalara iner.
İzole Deneyler
Yeni bir kütüphane veya veritabanı denemek istediğinizde, ana sisteminizi kirletmeden izole bir konteynerde test edebilirsiniz. Beğenmezseniz tek komutla silebilirsiniz.
Kaynak Verimliliği
Aynı anda birden fazla proje üzerinde çalışıyorsanız, her proje için ayrı konteyner grupları çalıştırabilir, işiniz bittiğinde durdurabilirsiniz.
Volume ve Ağ Yönetimi: Pratik İpuçları
Volume Kullanımı
Veritabanı gibi kalıcı veri saklayan servisler için volume kullanımı zorunludur:
# İsimli volume oluşturma
docker volume create my_data
# Volume'u konteynere bağlama
docker run -v my_data:/var/lib/postgresql/data postgres:16
# Bind mount (host dizinini bağlama)
docker run -v $(pwd)/logs:/app/logs my-app
Bind mount'lar özellikle geliştirme sırasında kod değişikliklerini anında görmek için idealdir. Ancak üretimde performans ve güvenlik açısından isimli volume'lar tercih edilmelidir.
Ağ Yapılandırması
Konteynerler arası iletişim için özel ağlar oluşturmak iyi bir pratiktir:
docker network create app_network
docker run --network app_network --name db postgres:16
docker run --network app_network --name web my-app
Aynı ağdaki konteynerler birbirlerine isimleriyle erişebilir. Bu, DNS tabanlı servis keşfini otomatik olarak sağlar.
Güvenlik ve En İyi Uygulamalar
Docker kullanırken güvenliği ihmal etmek ciddi sonuçlar doğurabilir. İşte dikkat etmeniz gereken noktalar:
- Root olmayan kullanıcı kullanın: Dockerfile'da
USERtalimatıyla root dışı bir kullanıcı tanımlayın. - Minimal temel imajlar seçin:
alpineveyadistrolessgibi küçük imajlar saldırı yüzeyini azaltır. - Sürümleri sabitleyin:
latestetiketi yerine spesifik sürümler kullanın. - Gereksiz araçları kaldırın: Üretim imajlarına debug araçları bırakmayın.
- Sırları yönetin: Şifreleri imaja gömmek yerine Docker Secrets veya ortam değişkenleri kullanın.
- İmaj taraması yapın:
docker scanveya Trivy gibi araçlarla güvenlik açıklarını tespit edin.
Çok aşamalı (multi-stage) build'ler de hem güvenlik hem de boyut açısından önemlidir:
# Build aşaması
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Üretim aşaması
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER node
CMD ["node", "dist/server.js"]
Sık Karşılaşılan Sorunlar ve Çözümleri
Konteyner Aniden Durduruluyor
Logları incelemek ilk adım olmalı:
docker logs <container_id>
Genellikle eksik ortam değişkeni veya yanlış başlangıç komutu nedeniyle olur.
Disk Alanı Tükeniyor
Kullanılmayan imaj, konteyner ve volume'ları temizleyin:
docker system prune -a --volumes
Bu komut tüm durdurulmuş konteynerleri, kullanılmayan imajları ve volume'ları siler. Dikkatli kullanın.
Port Çakışması
port is already allocated hatası alıyorsanız, host makinede o portu kullanan başka bir süreç var demektir:
lsof -i :3000
Farklı bir port eşlemesi kullanabilir veya çakışan süreci sonlandırabilirsiniz.
Yavaş Build Süreleri
Katman önbelleğini etkin kullanmak için Dockerfile'da sık değişmeyen talimatları üste koyun. package.json gibi bağımlılık dosyalarını, uygulama kodundan önce kopyalamak bu yüzden önemlidir.
Sonuç: Docker'ı Bir Alışkanlık Haline Getirin
Docker, öğrenme eğrisi olan ama karşılığını fazlasıyla veren bir teknolojidir. İlk başta komut satırı karmaşık görünebilir, ancak birkaç proje geliştirdikten sonra Docker'sız bir iş akışı düşünemez hale gelirsiniz. Özellikle ekip çalışmalarında, CI/CD süreçlerinde ve mikroservis mimarilerinde Docker'ın sağladığı tutarlılık paha biçilemezdir.
Bu rehberdeki adımları takip ederek kendi geliştirme ortamınızı Dockerize edebilir, ekip arkadaşlarınızla paylaşabilir ve üretim ortamına sorunsuz geçiş yapabilirsiniz. Unutmayın: Docker bir araçtır, ancak doğru kullanıldığında yazılım geliştirme kültürünüzü dönüştüren bir yaklaşımdır.
Bir sonraki adım olarak Kubernetes'e göz atmanızı öneririm. Konteynerleri tek makinede yönetmeyi öğrendikten sonra, onları bir küme üzerinde orkestre etmek doğal bir ilerleme olacaktır.