"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 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.

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 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: çalışan bir konteynerin içine terminal açar.sh 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.
Henüz yorum yok.
Sohbete katıl. Yorumlar yayınlanmadan önce moderasyondan geçer.