Docker ile ortam kurulumu - Kapsamlı Bakış

# 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: "Am...

Docker ile ortam kurulumu - Kapsamlı Bakış

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. alpine sü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 USER talimatıyla root dışı bir kullanıcı tanımlayın.
  • Minimal temel imajlar seçin: alpine veya distroless gibi küçük imajlar saldırı yüzeyini azaltır.
  • Sürümleri sabitleyin: latest etiketi 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 scan veya 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.

İLGİLİ İÇERİKLER

Bunları da Okumak İsteyebilirsiniz