Docker ve Linux Container Rehberi: Başlangıçtan İleri Seviyeye

Docker, uygulamaları bağımlılıklarıyla birlikte taşınabilir konteynerlere paketler. İmaj, Dockerfile, Compose ve volume kavramlarını komut örnekleriyle anlatıyoruz.

Programlar
Docker ve Linux Container Rehberi: Başlangıçtan İleri Seviyeye

"Benim makinemde çalışıyordu" cümlesini duymayan geliştirici yok gibidir. Kod kendi bilgisayarınızda sorunsuz çalışır, sonra sunucuya taşındığında hataya düşer; sebep genelde ortam farkıdır. Kütüphane sürümü tutmaz, işletim sistemi ayarı değişiktir ya da bir bağımlılık eksiktir. Docker, uygulamayı ve ihtiyaç duyduğu her şeyi tek bir taşınabilir birime, konteynere kapatarak bu sorunu ortadan kaldırır. Bu rehberde temel kavramlardan günlük kullanıma kadar sırayla ilerliyoruz.

Konteyner Nedir, Sanal Makineden Farkı Ne

Konteyner, bir uygulamanın çalışması için gereken kodu, kütüphaneleri ve ayarları tek bir pakette toplar. Uygulama bu paketin içinde, altta yatan işletim sisteminden bağımsız çalışır; bu yüzden geliştirme bilgisayarında da üretim sunucusunda da aynı şekilde davranır.

Sanal makine ile karıştırılır ama aralarındaki fark köklü. Sanal makine kendi işletim sistemini sıfırdan başlatır ve gigabaytlarca disk, RAM tüketir. Konteyner ise ana sistemin çekirdeğini doğrudan kullanır, bu yüzden başlaması saniyeler sürer.

Bu farkın sonucu kaynak kullanımında görülür. Aynı sunucuda birkaç sanal makine yerine düzinelerce, hatta yüzlerce konteyner çalıştırılabilir. Geliştirme ekiplerinin ve üretim ortamlarının konteyneri tercih etmesinin başlıca sebebi bu kaynak tasarrufu.

docker run hello-world

Bu komut, Docker kurulumunun doğru çalıştığını doğrulamak için kullanılır. Konteyner teknolojisine dair açık kaynak kaynaklara ek olarak Docker'ın resmî belgelerine de bakabilirsiniz; kurulumdan ileri yapılandırmaya kadar güncel bilgi orada.

Konteynerin asıl gücü, kodun geliştirmeden üretime kadar aynı biçimde davranmasından gelir. Bir uygulama bir kez konteynerleştirildiğinde dizüstü bilgisayarda, test ortamında ve canlı sunucuda birebir aynı şekilde çalışır. Dağıtım sırasında çıkan ortam kaynaklı hataların çoğu böylece baştan devre dışı kalır.

İmaj ve Konteyner Arasındaki İlişki

Docker iki kavram üzerine kurulu: imaj ve konteyner. İmaj, bir konteyneri oluşturmak için kullanılan salt okunur bir şablondur. Konteyner ise bu şablonun çalışan hâlidir; aynı imajdan istediğiniz sayıda bağımsız konteyner türetilebilir.

Docker imajı indirip çalıştıran terminal komutları
docker images
docker ps -a

İlk satır makinede kayıtlı imajları, ikinci satır çalışan ve durdurulmuş konteynerlerin tamamını gösterir. İmajlar katman katman oluşturulur; Docker her katmanı önbelleğe alır, böylece aynı adımı gereksiz yere tekrarlamaz.

İmajlar Docker Hub gibi kayıt defterlerinde tutulur ve resmî bir imajı indirmek tek satırlık bir işlemdir.

docker pull nginx:latest
docker run -d -p 8080:80 nginx:latest

Bu iki komutla bir web sunucusu indirilir ve 8080 portu üzerinden erişime açılır. Kurulum adımlarıyla uğraşmadan, hazır bir imajla birkaç dakikada çalışan bir servise sahip olursunuz.

Docker Hub'da veritabanı motorlarından programlama dili çalışma zamanlarına kadar binlerce resmî imaj yer alır. Kendi imajınızı da bir kayıt defterine yükleyip ekibinizle paylaşabilirsiniz; bu, her projeye sıfırdan başlama zorunluluğunu ortadan kaldırır.

Dockerfile ile Kendi İmajınızı Oluşturmak

Kendi uygulamanız için bir imaj hazırlamak istediğinizde bir Dockerfile yazarsınız. Bu dosya, imajın hangi adımlarla kurulacağını satır satır tanımlar.

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Dockerfile'daki her satır ayrı bir katman oluşturur ve değişmeyen katmanlar önbellekten okunur. Bu yüzden önce package.json kopyalanıp bağımlılıklar kurulur, kaynak kod en sona bırakılır: kodda küçük bir değişiklik yaptığınızda npm install adımı yeniden çalışmaz, derleme çok daha hızlı biter.

İmajı derlemek ve konteyneri başlatmak şu iki komutla olur.

docker build -t benim-uygulamam .
docker run -p 3000:3000 benim-uygulamam

İmajı küçük tutmak önemli. .dockerignore dosyasıyla gereksiz klasörleri dışarıda bırakmak hem imaj boyutunu düşürür hem de imaja gereksiz dosya sızmasını önler.

node_modules
.git
*.log

Docker Compose ile Çok Servisli Uygulamalar

Tek bir konteynerle sınırlı kalan uygulama azdır; çoğu projede bir web sunucusu, bir veritabanı ve bir önbellek servisi birlikte çalışır. Docker Compose, bu servislerin hepsini tek bir dosyada tanımlayıp birlikte yönetmenizi sağlar.

Docker Compose ile web ve veritabanı servislerinin birlikte çalışmasını gösteren şema
version: "3.8"
services:
  web:
    build: .
    ports:
      - "3000:3000"
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ornek

Bu tanım docker-compose.yml adıyla kaydedilir ve tek komutla bütün servisler birlikte başlar.

docker compose up -d

Ekibe yeni katılan biri, kurulum adımlarını tek tek takip etmek yerine bu tek komutla geliştirme ortamını dakikalar içinde ayağa kaldırabilir. docker compose down komutu ortamı aynı hızla kapatır; bu kolaylık, Compose'u küçük ve orta ölçekli projelerde günlük araç hâline getiriyor.

Servisler birbirini otomatik bulur. Yukarıdaki tanımda web servisi veritabanına db ismiyle erişebilir, çünkü Compose tüm servisleri aynı ağa bağlar ve isim üzerinden birbirlerine ulaşmalarını sağlar. IP adresi elle takip etmeye gerek kalmaz.

Veri Kalıcılığı: Volumes

Bir konteyner silindiğinde içindeki veriler de gider; konteynerler geçici olacak şekilde tasarlanmıştır. Ama bir veritabanı için bu kabul edilemez, çünkü konteyner her yeniden başladığında verinin yerinde durması gerekir. Docker bu sorunu volume denen mekanizmayla çözer.

Docker konteynerini kaynak sınırlarıyla çalıştıran terminal komutu
docker volume create veritabani_verisi
docker run -d -v veritabani_verisi:/var/lib/postgresql/data postgres:16

Bu iki satır veriyi konteynerin dışında, ayrı bir alanda tutar. Konteyner silinse bile veri kaybolmaz; yeni bir konteyner aynı volume'e bağlanıp kaldığı yerden devam eder.

Geliştirirken kodu kaydettiğiniz anda konteynerde görmek isterseniz bind mount kullanılır.

docker run -v $(pwd):/app -p 3000:3000 benim-uygulamam

Bu komutla ana sistemdeki klasör konteynerin içine doğrudan bağlanır; kodu editörde değiştirdiğinizde imajı yeniden derlemeden değişiklik konteynerde görünür.

Volume ile bind mount farklı amaçlara hizmet eder. Volume, Docker'ın kendi yönettiği ve taşınabilir olan bir depolama alanıdır; bind mount ise ana sistemdeki belirli bir klasörü doğrudan içeri açar. Üretimde kalıcı veri için volume, geliştirirken anlık kod senkronizasyonu için bind mount daha uygundur.

Güvenlik ve Üretim Notları

Kaynağı belirsiz imajları çalıştırmak risk taşır; mümkün olduğunca resmî ya da doğrulanmış yayıncıların imajlarını tercih edin. İmajları düzenli aralıklarla güncellemek, bilinen açıkları kapatmanın en basit yolu.

Konteyneri root kullanıcıyla çalıştırmayın. Dockerfile içinde ayrı bir kullanıcı tanımlamak, olası bir güvenlik açığının konteyner dışına taşma riskini azaltır.

RUN adduser -D appuser
USER appuser

Kaynak sınırı tanımlamak da üretimde gereklidir. Sınır konmazsa hatalı çalışan tek bir konteyner sunucudaki tüm belleği veya işlemciyi tüketip diğer servisleri de durdurabilir.

docker run --memory=512m --cpus=1 benim-uygulamam

Güvenilir imaj seçmek, root'suz çalıştırmak ve kaynak sınırı koymak; üretimde Docker kullanırken atılacak ilk üç adım budur.

Öğrenmeye Nereden Başlamalı

Docker'ı öğrenmenin en hızlı yolu küçük bir uygulamayı gerçekten konteynerleştirmek. Elinizdeki bir Node.js ya da Python projesine bir Dockerfile ekleyin, docker build ve docker run ile çalıştırın. Bu pratik, uzun bir dokümantasyonu baştan sona okumaktan daha kısa sürede kalıcı bilgiye dönüşür.

Temel komutlara alıştıktan sonra sırada Compose var; bir web uygulamasını veritabanıyla birlikte ayağa kaldırmak gerçek projelere en yakın alıştırma. Yüzlerce konteyneri aynı anda yönetmek gerektiğinde Kubernetes gibi orkestrasyon araçları devreye girer, ama günlük geliştirme ve küçük ölçekli dağıtımlarda Docker ile Compose çoğu ihtiyacı karşılar.

Aşağıdaki komutlar sık kullanılır, ezberlemeye değer:

  • docker ps: çalışan konteynerleri listeler.
  • docker logs : bir konteynerin loglarını gösterir.
  • docker exec -it sh: çalışan bir konteynerin içine terminal açar.
  • docker system prune: kullanılmayan imaj ve konteynerleri temizler.

Bu dört komut günlük hata ayıklama ve bakım işlerinin büyük kısmını çözer. Docker'a bir kez alıştıktan sonra kurulum karmaşasının nasıl azaldığı, her projenin kendi izole ortamında çalıştığı fark edilir.

Celil Uyanikoglu

Yazan Celil Uyanikoglu

Bilgisayar mühendisiyim; 25 yılı aşkın süredir bilgi işlem sektörünün içindeyim. Bu blogu 2020'de, işimde her gün karşılaştığım sorunların çözümlerini bir yere yazmak için açtım: Linux, güvenlik, tarayıcılar, yapay zeka araçları. Yazdığım her rehberi önce kendi bilgisayarımda ya da sunucumda deniyorum; çalıştığını görmediğim adımı yayınlamam. Hatalı ya da eskimiş bir şey görürsen iletişim sayfasından yaz — düzeltirim.

Yorum

Henüz yorum yok.

Sohbete katıl. Yorumlar yayınlanmadan önce moderasyondan geçer.

Yorum yap

E-posta adresin yayınlanmaz. Yorumlar moderasyondan sonra yayınlanır.

Sırada

İlgili notlar