· 6 dk okuma

Docker ve Docker Compose Kurulumu: Ubuntu/Debian Rehberi

Docker ve Docker Compose kurulumu için Ubuntu veya Debian'da en doğru yol, dağıtımın eski docker.io paketi yerine Docker'ın kendi resmi apt deposunu kullanmaktır. Bu rehberde depoyu ekleyip docker-ce ile docker-compose-plugin paketlerini kuracak, ilk konteynerinizi çalıştıracak, compose ile küçük bir web uygulaması ayağa kaldıracak ve üretimde işinize yarayacak güvenlik ayarlarına bakacağız.

Komutlar Ubuntu 22.04/24.04 ve Debian 11/12 üzerinde root olmayan, sudo yetkili bir kullanıcıyla çalıştırılacak şekilde yazıldı. Sunucunuz yeniyse önce SSH ve güvenlik duvarı gibi temel ayarları tamamlamanız iyi olur.

Ön Hazırlık: Eski Paketleri Kaldırın

Daha önce dağıtım depolarından Docker benzeri paketler kurduysanız çakışmayı önlemek için kaldırın. Konteyner ve volume verileriniz /var/lib/docker altında olduğundan bu işlem onlara dokunmaz.

for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do
  sudo apt-get remove -y $pkg
done

Paket yüklü değilse apt sadece bilgi verir, sorun değildir.

Resmi Docker Deposunu Ekleme

Ubuntu için

sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Debian için

URL ve dağıtım adı değişir, geri kalanı aynıdır:

sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker Engine ve Compose Eklentisini Kurma

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Kurulum bitince servis otomatik başlar ve açılışta çalışacak şekilde etkinleşir. Kontrol edin:

sudo systemctl status docker --no-pager
docker --version
docker compose version

Dikkat: Güncel kurulumda komut docker-compose (tire ile, eski Python sürümü) değil, docker compose (boşlukla, Compose v2 eklentisi) şeklindedir.

İlk Konteyner: hello-world ve Nginx

sudo docker run hello-world

Çıktıda "Hello from Docker!" görüyorsanız imaj indirme, konteyner oluşturma ve çalıştırma zinciri çalışıyor demektir. Şimdi gerçek bir servis deneyelim:

sudo docker run -d --name test-nginx -p 127.0.0.1:8080:80 nginx:stable-alpine
curl -I http://127.0.0.1:8080
sudo docker ps
sudo docker logs test-nginx
sudo docker rm -f test-nginx

-p 127.0.0.1:8080:80 ifadesine dikkat edin: portu sadece yerel arayüze bağlıyoruz. Nedenini güvenlik bölümünde açıklıyoruz.

Her seferinde sudo yazmamak için

sudo usermod -aG docker $USER
newgrp docker
docker ps

Uyarı: docker grubundaki bir kullanıcı fiilen root yetkisine eşdeğerdir. Bu gruba yalnızca güvendiğiniz hesapları ekleyin.

Docker Compose ile Web Uygulaması

Örnek olarak bir Nginx web sunucusu ve bir PostgreSQL veritabanından oluşan basit bir yapı kuralım. Önce klasör ve dosyaları hazırlayın:

mkdir -p ~/webapp/html && cd ~/webapp
echo '<h1>Merhaba, Docker Compose!</h1>' > html/index.html

.env dosyası (parolayı kendi değerinizle değiştirin):

cat > .env <<'EOF'
POSTGRES_DB=appdb
POSTGRES_USER=appuser
POSTGRES_PASSWORD=guclu-bir-parola-yazin
EOF
chmod 600 .env

compose.yaml dosyası:

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      db:
        condition: service_healthy
    networks:
      - frontend
      - backend
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    env_file: .env
    volumes:
      - dbdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend
    restart: unless-stopped

networks:
  frontend:
  backend:
    internal: true

volumes:
  dbdata:

Burada üç önemli nokta var: veritabanının hiçbir portu dışarı yayımlanmıyor, backend ağı internal olduğu için dış dünyaya çıkışı da yok ve veriler dbdata adlı volume'da kalıcı. Yeni Compose sürümlerinde dosyanın başına version: satırı yazmanıza gerek yoktur.

Başlatın ve doğrulayın:

docker compose config        # yazım hatası kontrolü
docker compose up -d
docker compose ps
curl http://127.0.0.1:8080

Günlük işlemler için sık kullanılan komutlar:

Komut Ne yapar
docker compose logs -f web Servisin canlı logları
docker compose pull && docker compose up -d İmajları günceller, değişenleri yeniden oluşturur
docker compose restart web Tek servisi yeniden başlatır
docker compose down Konteyner ve ağları siler, volume'lar kalır
docker compose down -v Volume'ları da siler (veri kaybı!)

Siteyi internete açmak için 127.0.0.1:8080'e önünde bir ters vekil (reverse proxy) ve TLS ile erişmek en temiz yöntemdir. Nginx ve Certbot ayarı için ayrı rehberimize bakabilirsiniz.

Güvenlik İpuçları

1. Docker, UFW'yi atlar

En sık yapılan hata budur. -p 8080:80 ile yayımlanan bir port, Docker'ın eklediği iptables kuralları nedeniyle UFW'de "deny" olsa bile dışarıdan erişilebilir olabilir. Çözüm basit: dışarı açmanız gerekmeyen her portu 127.0.0.1: önekiyle yayımlayın ve dışarıya yalnızca ters vekil üzerinden 80/443 açın. Veritabanı, Redis gibi servislere hiç ports: yazmayın; aynı compose ağındaki servisler birbirine servis adıyla erişir.

Kontrol için dışarıdan bir nmap taraması ya da sunucuda şu komut işinize yarar:

sudo ss -tlnp | grep -E 'docker-proxy|:8080'

2. docker.sock'u konteynere bağlamayın

/var/run/docker.sock dosyasını bir konteynere mount etmek, o konteynere sunucunun tam kontrolünü vermek demektir. Gerçekten gerekiyorsa (örneğin bir izleme aracı) salt okunur bir socket vekili kullanın ve güvenilir imajlarla sınırlayın.

3. Konteyneri en az yetkiyle çalıştırın

Uygulama servisleriniz için uygun olduğu ölçüde şu ayarları ekleyin:

    user: "1000:1000"
    read_only: true
    tmpfs:
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true

Her imaj bu kısıtlarla çalışmaz; hata alırsanız cap_add ile yalnızca gereken yetkiyi geri verin.

4. İmaj etiketlerini sabitleyin, güncel tutun

latest yerine nginx:1.27-alpine gibi belirli etiketler kullanın. Mümkünse resmi (Docker Official) veya doğrulanmış yayıncıların imajlarını tercih edin. Düzenli olarak docker compose pull yapıp yeniden oluşturun.

5. Gizli bilgileri imaja gömmeyin

Parolalar için .env (chmod 600) veya Compose secrets kullanın; .env dosyasını Git'e eklemeyin (.gitignore).

6. Log rotasyonunu ayarlayın

Varsayılan json-file sürücüsünde log boyutu sınırsızdır ve diski doldurabilir. /etc/docker/daemon.json dosyasını oluşturun:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
sudo systemctl restart docker

Bu ayar yalnızca yeni oluşturulan konteynerlere uygulanır; mevcutları docker compose up -d --force-recreate ile yeniden oluşturun.

Yaygın Hatalar ve Çözümleri

Üretim İçin Altyapı Notu

Docker'ı geliştirme ortamında laptopta denemek kolaydır, ancak üretim için kaynakların size ayrılmış olması, ağ erişiminin öngörülebilir olması ve gerektiğinde saldırı trafiğinin filtrelenebilmesi önemlidir. Konteynerlerinizi, kendi kaynaklarınıza sahip bir VDS sunucuda çalıştırabilirsiniz. Herkese açık servisler barındırıyorsanız DDoS koruma ve firewall seçeneklerini de gözden geçirmenizi öneririz; çünkü Docker'ın yayımladığı portlar ağ katmanı saldırılarına karşı kendi başına bir koruma sağlamaz.

Özet

  1. Eski paketleri kaldırın, resmi Docker deposunu ekleyin.
  2. docker-ce ve docker-compose-plugin paketlerini kurun; docker compose version ile doğrulayın.
  3. Servisleri compose ile tanımlayın, veritabanı gibi servisleri dışarı açmayın.
  4. Portları 127.0.0.1 ile sınırlayın, UFW'nin Docker'ı kısıtlamadığını unutmayın.
  5. Log rotasyonu, sabit imaj etiketleri ve en az yetki ilkesini uygulayın.

Sık sorulan sorular

Docker ve Docker Compose'u ayrı ayrı kurmam gerekir mi?

Hayır. Resmi depodan docker-compose-plugin paketini kurduğunuzda Compose v2, docker komutuna eklenti olarak gelir ve docker compose şeklinde kullanılır. Ayrı bir docker-compose ikilisi kurmanız gerekmez.

docker.io paketi ile docker-ce arasındaki fark nedir?

docker.io, Ubuntu/Debian deposundaki dağıtım tarafından paketlenen sürümdür ve genelde daha eskidir. docker-ce, Docker'ın kendi deposundan gelen güncel Engine sürümüdür ve Compose ile Buildx eklentileri aynı depodan güncellenir.

UFW kuralları Docker konteyner portlarını neden engellemiyor?

Docker, yayımlanan portlar için doğrudan iptables kuralları ekler ve bu trafik UFW'nin zincirlerinden önce işlenebilir. En güvenli çözüm, gerekmeyen portları 127.0.0.1 ile yayımlamak ve dış erişimi bir ters vekil üzerinden vermektir.

Kullanıcıyı docker grubuna eklemek güvenli mi?

Docker grubu üyeleri fiilen root yetkisine sahip olur, çünkü konteyner içine sunucu dosya sistemini bağlayabilirler. Bu gruba yalnızca güvendiğiniz yönetici hesaplarını ekleyin; diğer kullanıcılar için sudo veya rootless Docker düşünün.

Konteynerleriniz için kaynakları size ayrılmış bir VDS'i inceleyin.İncele