Docker ile containerizasyon: Modern geliştirme iş akışı

Docker nedir, nasıl çalışır? Container teknolojisi ve Dockerfile en iyi pratikleri.

2026-03-1515 dk okuma
Docker ile containerizasyon: Modern geliştirme iş akışı

Yazılım geliştiren her ekibin er ya da geç karşılaştığı bir cümle vardır: "Benim makinemde çalışıyordu." Bir geliştiricinin bilgisayarında sorunsuz çalışan kod, test sunucusunda patlar; test sunucusunda yeşil ışık yakan uygulama, canlı ortamda beklenmedik hatalar üretir. Bu kaosun ardında genellikle aynı sebep yatar: ortamlar arasındaki tutarsızlık. İşletim sistemi sürümleri, kütüphane versiyonları, çevre değişkenleri ve sistem bağımlılıkları her makinede biraz farklıdır ve bu küçük farklar üst üste binince saatler süren hata ayıklama oturumlarına dönüşür.

Docker tam olarak bu sorunu çözmek için doğdu ve son on yılda yazılım geliştirme kültürünü kökten değiştirdi. Bir uygulamayı, çalışması için ihtiyaç duyduğu her şeyle birlikte tek bir taşınabilir pakete koyma fikri, hem geliştiricilerin günlük hayatını kolaylaştırdı hem de mikroservis mimarileri, sürekli dağıtım ve bulut tabanlı altyapıların önünü açtı. Bu yazıda Docker'ın ne olduğunu, container teknolojisinin nasıl çalıştığını, Dockerfile yazımının inceliklerini ve üretim ortamında containerizasyonu sağlıklı kurmanın yollarını somut örneklerle ele alacağız. İstanbul merkezli bir yazılım ajansı olarak farklı sektörlerden onlarca projede Docker'ı sahada kullandık; bu deneyimden çıkardığımız pratik dersleri de paylaşacağız.

Docker nedir ve neden geliştirme dünyasını değiştirdi?

Docker, uygulamaları "container" adı verilen hafif, izole ve taşınabilir birimler içinde paketleyip çalıştırmamızı sağlayan açık kaynaklı bir platformdur. Bir container, uygulamanızın kodunu; çalışma zamanını (runtime); sistem araçlarını, kütüphaneleri ve yapılandırmaları tek bir paket içinde barındırır. Bu paket, üzerinde çalıştığı makinenin işletim sistemi çekirdeğini paylaşır ama dosya sistemi, ağ ve süreç alanı açısından diğer container'lardan yalıtılmıştır.

Bu yaklaşımın getirdiği en büyük değer "tutarlılık"tır. Bir geliştiricinin dizüstü bilgisayarında oluşturulan container imajı, hiçbir değişiklik gerektirmeden test ortamında, ön üretim ortamında ve canlı sunucularda aynı şekilde çalışır. Çünkü artık taşınan şey sadece kod değil, kodun içinde yaşadığı ortamın tamamıdır. "Bende çalışıyordu" sorununun kökten çözülmesinin sebebi budur.

Docker'ın bir diğer dönüştürücü etkisi hız üzerindedir. Geleneksel sanal makinelerin aksine container'lar saniyeler içinde başlar, çok daha az kaynak tüketir ve aynı donanım üzerinde çok daha fazla iş yükü çalıştırılmasına olanak tanır. Bu, hem geliştirme döngülerini hızlandırır hem de altyapı maliyetlerini düşürür. Özellikle bulut faturalarının döviz kuruna bağlı olarak ciddi yük oluşturduğu Türkiye pazarında, kaynak verimliliği doğrudan bütçeye yansıyan bir avantaja dönüşür.

Container teknolojisi ve modern yazılım altyapısını temsil eden sunucu görseli

Sanal makineler ile container arasındaki temel fark

Docker'ı doğru anlamak için onu sıkça karıştırıldığı sanal makinelerle (VM) karşılaştırmak gerekir. Sanal makineler, fiziksel bir sunucu üzerinde hipervizör adı verilen bir katman aracılığıyla çalışan, kendi tam işletim sistemine sahip izole ortamlardır. Her sanal makine kendi çekirdeğini, sürücülerini ve sistem kaynaklarını taşır. Bu güçlü bir izolasyon sağlar ama beraberinde ağırlık getirir.

Container'lar ise işletim sistemi seviyesinde sanallaştırma yapar. Yani aynı çekirdeği paylaşırlar ve sadece uygulamanın ihtiyaç duyduğu katmanları taşırlar. Bu sayede bir container, megabaytlar mertebesinde yer kaplarken, eşdeğer bir sanal makine gigabaytlar tutabilir. Başlangıç süresi açısından da fark dramatiktir: bir VM'in açılması dakikalar alabilirken, bir container milisaniyeler veya saniyeler içinde ayağa kalkar.

ÖzellikSanal Makine (VM)Container (Docker)
Yalıtım seviyesiDonanım/çekirdek seviyesinde tam yalıtımİşletim sistemi seviyesinde yalıtım
Başlangıç süresiDakikalarSaniyeler veya daha kısa
Disk kullanımıGigabaytlarMegabaytlar
Kaynak verimliliğiDüşük (her VM ayrı OS taşır)Yüksek (çekirdek paylaşımı)
Aynı donanımda yoğunlukSınırlıÇok yüksek
TaşınabilirlikOrta (imajlar büyük)Çok yüksek (hafif imajlar)
Tipik kullanımFarklı işletim sistemleri, güçlü izolasyonMikroservisler, hızlı dağıtım, CI/CD

Bu karşılaştırma "VM kötü, container iyi" anlamına gelmez. İkisi farklı ihtiyaçlara hizmet eder ve çoğu modern altyapıda birlikte kullanılırlar: container'lar genellikle sanal makineler üzerinde çalıştırılır. Ancak uygulama paketleme, dağıtım hızı ve kaynak verimliliği söz konusu olduğunda container'lar açık ara öne çıkar.

Docker mimarisi: Motor, imaj, container ve registry

Docker'ın günlük kullanımına geçmeden önce temel kavramları netleştirmek, ileride yaşanacak kafa karışıklığını önler. Docker ekosistemi birkaç ana bileşen üzerine kuruludur.

Docker Engine

Docker Engine, container'ları oluşturan ve çalıştıran çekirdek motordur. İstemci (CLI) ile arka planda çalışan daemon (dockerd) arasındaki iletişimi yönetir. Terminalde yazdığınız komutlar istemciye gider, istemci de bu komutları daemon'a iletir ve asıl işi daemon yapar. Bu istemci-sunucu mimarisi, uzaktaki bir Docker sunucusunu yerel makinenizden yönetebilmenizi de sağlar.

İmaj (image)

İmaj, bir container'ın salt okunur şablonudur. İçinde uygulamanız, bağımlılıklarınız ve çalışma ortamınız katman katman paketlenmiştir. Bir imaj değişmezdir; onu çalıştırdığınızda ondan bir container örneği yaratılır. İmajlar katmanlı bir yapıya sahiptir ve her katman bir önceki üzerine eklenir. Bu katmanlı yapı, hem disk kullanımını optimize eder hem de build süreçlerini hızlandırır.

Container

Container, bir imajın çalışan örneğidir. Aynı imajdan onlarca container oluşturabilirsiniz; her biri kendi yazılabilir katmanına, kendi süreç alanına ve kendi ağ kimliğine sahiptir. Container durdurulduğunda yazılabilir katmandaki geçici veriler kaybolur; kalıcı veri için "volume" adı verilen yapılar kullanılır.

Registry

Registry, imajların depolandığı ve paylaşıldığı merkezi depodur. Docker Hub en bilinen genel registry'dir, ancak kurumsal projelerde genellikle özel registry'ler tercih edilir. Bir imajı build ettikten sonra registry'ye gönderir (push), başka bir ortamda oradan indirip (pull) çalıştırırsınız. Bu akış, container tabanlı dağıtımın bel kemiğini oluşturur.

İlk Dockerfile'ınızı adım adım yazmak

Dockerfile, bir imajın nasıl oluşturulacağını tarif eden basit bir metin dosyasıdır. Her satır bir talimat içerir ve bu talimatlar sırayla işlenerek imaj katmanları üretilir. Örnek olarak basit bir Node.js uygulaması için Dockerfile'ı ele alalım:

FROM node:20-alpine
WORKDIR /uygulama
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Bu kısa dosya aslında çok şey anlatır. FROM satırı, üzerine inşa edeceğimiz temel imajı belirtir; burada hafif Alpine Linux tabanlı Node.js 20 imajını seçtik. WORKDIR, sonraki komutların çalışacağı dizini ayarlar. İlk olarak yalnızca paket tanım dosyalarını kopyalayıp bağımlılıkları yüklememizin sebebi katman önbelleğidir: kod değişse bile bağımlılıklar değişmediği sürece npm adımı yeniden çalışmaz. Ardından tüm kaynak kodu kopyalar, uygulamanın dinlediği portu belgeler ve son olarak container başladığında çalışacak komutu tanımlarız.

İmajı oluşturmak ve çalıştırmak için kullanılan temel komutlar şu şekildedir:

docker build -t benim-uygulamam:1.0 .
docker run -d -p 3000:3000 --name web benim-uygulamam:1.0
docker ps
docker logs web

İlk komut bulunduğunuz dizindeki Dockerfile'ı kullanarak etiketli bir imaj üretir. İkinci komut bu imajdan arka planda çalışan bir container başlatır ve makinenizin 3000 portunu container'ın 3000 portuna bağlar. Diğer iki komutla çalışan container'ları listeler ve günlüklerini incelersiniz. Bu birkaç satırla bir uygulamayı tamamen izole, tekrarlanabilir bir ortamda ayağa kaldırmış olursunuz.

Dockerfile için en iyi pratikler

Bir Dockerfile yazmak kolaydır; iyi bir Dockerfile yazmak ise tecrübe ister. Aşağıdaki pratikler, sahada karşılaştığımız sorunlardan damıtılmıştır ve hem güvenlik hem performans açısından fark yaratır.

Katman önbelleğini doğru kullanın

Docker, her talimatı bir katman olarak önbelleğe alır. Bir katman değişmediği sürece sonraki build'lerde yeniden kullanılır. Bu yüzden sık değişen şeyleri (kaynak kod) dosyanın sonuna, nadir değişenleri (bağımlılık kurulumu) başına koymak build sürelerini ciddi biçimde kısaltır. Yukarıdaki örnekte package dosyalarını kopyalamayı kaynak kodu kopyalamadan önce yapmamızın sebebi tam olarak budur.

Çok aşamalı (multi-stage) build kullanın

Derleme araçları ve geliştirme bağımlılıkları nihai imajda yer almamalıdır. Çok aşamalı build ile uygulamayı bir aşamada derler, yalnızca ihtiyaç duyulan çıktıyı küçük bir son imaja kopyalarsınız:

FROM node:20-alpine AS derleme
WORKDIR /uygulama
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine AS calisma
COPY --from=derleme /uygulama/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Bu yaklaşımda derleme aşamasındaki tüm geçici dosyalar nihai imaja taşınmaz; sonuçta yüzlerce megabayt yerine yalnızca onlarca megabaytlık bir imaj elde edersiniz.

İmaj boyutunu küçük tutun ve güvenliği gözetin

Küçük imajlar daha hızlı taşınır, daha az saldırı yüzeyi sunar ve registry maliyetini düşürür. Aşağıdaki kontrol listesi pratikte en çok işe yarayan adımları özetler:

  • Mümkün olduğunca Alpine veya slim varyantları gibi küçük temel imajları tercih edin.
  • Gereksiz dosyaları .dockerignore ile build bağlamından çıkarın (node_modules, .git, log dosyaları gibi).
  • Container'ı root yerine yetkisiz bir kullanıcıyla çalıştırın; USER talimatı bu iş içindir.
  • Sabit sürüm etiketleri kullanın; latest etiketi tekrarlanabilirliği bozar.
  • Bir RUN talimatında birden fazla komutu zincirleyerek katman sayısını azaltın ve geçici dosyaları aynı katmanda temizleyin.
  • İmajlarınızı düzenli olarak güvenlik taramasından geçirin ve temel imajları güncel tutun.

Docker Compose ile çok servisli uygulamalar

Gerçek dünya uygulamaları nadiren tek bir container'dan ibarettir. Tipik bir web uygulaması; bir API servisi, bir veritabanı, bir önbellek katmanı ve belki bir arka plan işçisi içerir. Bunların hepsini elle tek tek başlatmak zahmetlidir. Docker Compose, birden fazla container'ı tek bir yapılandırma dosyasıyla tanımlayıp tek komutla yönetmenizi sağlar.

services:
  web:
    build: .
    ports:
      - "3000:3000"
    depends_on:
      - veritabani
    environment:
      DB_HOST: veritabani
  veritabani:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: gizli_parola
    volumes:
      - veri:/var/lib/postgresql/data
volumes:
  veri:

Bu dosyada web servisi yerel Dockerfile'dan build edilir, veritabanı ise hazır PostgreSQL imajından çalışır. depends_on ile başlatma sırası belirtilir, volumes ile veritabanı verisi kalıcı hale getirilir. Tek bir "docker compose up" komutuyla tüm yığını ayağa kaldırır, "docker compose down" ile tamamını kapatırsınız. Geliştirme ortamlarında bu, yeni ekip üyelerinin dakikalar içinde projeyi çalışır hale getirmesi anlamına gelir.

Yazılım ekibinin container tabanlı mimari üzerinde çalışmasını gösteren görsel

Container güvenliği ve yaygın riskler

Container'ların hafifliği ve hızı kadar güvenliği de ciddiye alınmalıdır. Yanlış yapılandırılmış bir container, tüm sunucuyu riske atabilir. Güvenliği katmanlı düşünmek gerekir: imaj, çalışma zamanı ve ağ.

İmaj seviyesinde en sık karşılaşılan risk, güncel olmayan veya güvenilmeyen temel imajların kullanılmasıdır. Bilinen güvenlik açıkları taşıyan bir temel imaj, üzerine ne inşa ederseniz edin bu açıkları taşımaya devam eder. Bu yüzden imajları düzenli taramak ve güncel tutmak şarttır. Çalışma zamanında ise container'ları root kullanıcısıyla çalıştırmak, gereksiz yetkiler vermek ve sınırsız kaynak tüketimine izin vermek tipik hatalardır.

Aşağıdaki önlemler, container güvenliğinin temelini oluşturur:

  • Container'ları yetkisiz kullanıcıyla çalıştırın ve gereksiz Linux yeteneklerini kaldırın.
  • CPU ve bellek limitleri tanımlayarak bir container'ın tüm sunucuyu tüketmesini engelleyin.
  • Sırları (şifre, API anahtarı) imaja gömmeyin; gizli yönetim araçları veya çevre değişkenleri kullanın.
  • Salt okunur dosya sistemi ile container'ları çalıştırarak değişikliğe karşı sertleştirin.
  • Yalnızca gerekli portları açın ve servisler arası ağ trafiğini sınırlayın.

Güvenlik, kurulduktan sonra unutulacak bir şey değildir; sürekli izleme ve güncelleme gerektirir. Bu noktada düzenli güvenlik denetimleri ve izleme süreçleri, container tabanlı altyapıların sağlığı için kritik önemdedir. Bakım, izleme ve destek hizmetlerimiz tam da bu sürekliliği sağlamaya odaklanır.

Production ortamında Docker: Orkestrasyon ve izleme

Birkaç container'ı bir makinede çalıştırmak ile yüzlerce container'ı onlarca sunucu üzerinde, kesintisiz ve ölçeklenebilir biçimde yönetmek tamamen farklı problemlerdir. İkinci senaryo "orkestrasyon" alanına girer ve burada Kubernetes endüstri standardı haline gelmiştir. Kubernetes; container'ları otomatik dağıtır, sağlıksız olanları yeniden başlatır, yüke göre ölçekler ve sıfır kesintili güncellemeler yapar.

Ancak her proje Kubernetes'e ihtiyaç duymaz. Küçük ve orta ölçekli uygulamalar için Docker Compose veya daha hafif orkestrasyon çözümleri çoğu zaman yeterlidir. Kurumsal ölçekte trafik, çoklu bölge dağıtımı ve karmaşık ölçekleme ihtiyaçları ortaya çıktığında Kubernetes devreye girer. Doğru aracı seçmek, ekibin olgunluğuna ve uygulamanın gerçek gereksinimlerine bağlıdır; gereğinden karmaşık bir altyapı, kazandırdığından fazlasını maliyet ve bakım yükü olarak geri alır.

Production ortamında container kullanırken izleme (monitoring) vazgeçilmezdir. Container'lar kısa ömürlü olabildiği için geleneksel sunucu izleme yaklaşımları yetersiz kalır. Merkezi günlük toplama, metrik izleme ve uyarı sistemleri kurmadan production'a container göndermek, gözleri kapalı araba kullanmaya benzer. Containerizasyonu CI/CD süreçleriyle birleştirmek ise dağıtımı tamamen otomatik ve güvenilir hale getirir; bu konuyu daha derinlemesine incelemek için CI/CD pipeline kurulumu rehberimize göz atabilirsiniz.

Türkiye pazarında Docker: Tipik senaryolar ve maliyet

Türkiye'deki yazılım ekipleri için Docker'ın en somut faydalarından biri maliyet kontrolüdür. Bulut sağlayıcılarının fiyatları döviz bazlı olduğundan, kaynak verimliliği doğrudan TL cinsinden bütçeye yansır. Container'ların aynı donanım üzerinde çok daha yüksek yoğunlukta çalışabilmesi, sunucu sayısını ve dolayısıyla faturayı azaltır.

Sahada en sık karşılaştığımız Docker kullanım senaryolarını şöyle özetleyebiliriz: yeni geliştiricilerin projeye dakikalar içinde dahil olabildiği tutarlı geliştirme ortamları; e-ticaret platformlarında kampanya dönemlerinde hızlı yatay ölçekleme; eski (legacy) uygulamaların container'a alınarak modern altyapıya taşınması; ve mikroservis mimarilerine kademeli geçiş. Bu senaryoların her birinde container'ların taşınabilirliği, ekibe bulut sağlayıcısına bağımlı kalmama özgürlüğü de kazandırır.

Doğru bulut altyapısını seçmek, container stratejisinin başarısını belirleyen önemli bir karardır. Hangi sağlayıcının, hangi bölgenin ve hangi hizmet modelinin projenize uygun olduğunu değerlendirirken bulut altyapısı nasıl seçilir yazımız yol gösterici olacaktır. Kurumsal düzeyde container mimarisi tasarımı, CI/CD entegrasyonu ve bulut göçü için bulut ve DevOps hizmetlerimiz kapsamında uçtan uca destek sağlıyoruz.

Docker kullanırken en sık yapılan hatalar

Onlarca projede tekrar eden bazı hatalar var ki, bunları baştan bilmek ekibinize çok zaman kazandırır. İşte sahadan derlediğimiz en yaygın tuzaklar:

  • Latest etiketine güvenmek: "latest" sabit bir sürümü garanti etmez; bugün çalışan imaj yarın farklı davranabilir. Her zaman belirli sürüm etiketleri kullanın.
  • Verileri container içinde tutmak: Container silindiğinde verisi de gider. Kalıcı veriler mutlaka volume'lerde saklanmalıdır.
  • Devasa imajlar üretmek: Tek aşamalı build ile derleme araçlarını nihai imaja dahil etmek, gereksiz büyük ve yavaş imajlar oluşturur.
  • Sırları imaja gömmek: Şifre veya API anahtarını Dockerfile'a yazmak ciddi bir güvenlik açığıdır; bu bilgiler imaj geçmişinde kalır.
  • Tek container'a her şeyi yığmak: Veritabanı, uygulama ve önbelleği tek container'a koymak, container felsefesine aykırıdır ve ölçeklemeyi imkânsız kılar. Her container tek bir sorumluluk taşımalıdır.
  • Sağlık kontrolü tanımlamamak: Healthcheck olmadan orkestratör, container'ın gerçekten sağlıklı olup olmadığını bilemez.

Bu hatalardan kaçınmak, hem geliştirme deneyimini iyileştirir hem de production ortamında yaşanacak sürprizleri önler. Container tabanlı bir web uygulamasını sıfırdan kurarken bu pratikleri baştan uygulamak, sonradan düzeltmekten çok daha kolaydır; web geliştirme hizmetlerimiz kapsamında projelerinizi en başından container dostu mimarilerle tasarlıyoruz.

Sıkça Sorulan Sorular

Docker öğrenmek ne kadar zaman alır?

Temel kavramları (imaj, container, Dockerfile, temel komutlar) birkaç gün içinde öğrenip basit projelerde kullanmaya başlayabilirsiniz. Ancak çok aşamalı build, ağ yönetimi, güvenlik sertleştirme ve orkestrasyon gibi ileri konularda ustalaşmak haftalar hatta aylar süren pratik gerektirir. İyi haber şu ki, temel bilgilerle bile günlük geliştirme verimliliğinizde anında fark hissedersiniz.

Docker küçük projeler için aşırı mı kaçar?

Hayır. Aksine, küçük projelerde bile Docker, ortam tutarlılığı ve kolay kurulum sayesinde değer katar. Özellikle ekibe yeni katılan birinin projeyi tek komutla ayağa kaldırabilmesi, küçük ekipler için bile büyük bir kazançtır. Tek geliştiricili kişisel projeler için bazen gereksiz görülse de, birden fazla kişinin dokunduğu her projede Docker neredeyse her zaman kazandırır.

Docker ile Kubernetes arasındaki fark nedir?

Docker container oluşturma ve çalıştırma teknolojisidir; Kubernetes ise bu container'ları büyük ölçekte yöneten orkestrasyon platformudur. Docker tek tek container'larla, Kubernetes ise yüzlerce container'ın dağıtımı, ölçeklenmesi ve dayanıklılığıyla ilgilenir. İkisi rakip değil, tamamlayıcıdır: Kubernetes genellikle Docker container'larını yönetir.

Windows ve macOS'ta Docker nasıl çalışır?

Container'lar Linux çekirdeğine dayandığı için Windows ve macOS'ta Docker, arka planda hafif bir Linux sanal makinesi üzerinden çalışır. Docker Desktop bu süreci sizin için yönetir, böylece komutlar her platformda aynı şekilde çalışır. Üretim ortamları genellikle Linux tabanlı olduğundan, geliştirmeyi de Linux container'larıyla yapmak tutarlılığı korur.

Mevcut bir uygulamayı container'a almak zor mu?

Zorluk derecesi uygulamanın mimarisine bağlıdır. Bağımlılıkları net, durumu (state) dışarı taşınabilen modern uygulamaları container'a almak nispeten kolaydır. Sistemle sıkı bağlı, çok sayıda yerel bağımlılığı olan eski uygulamalarda ise süreç daha dikkatli planlama gerektirir. Çoğu durumda kademeli bir geçiş stratejisi en sağlıklı yoldur.

Sonuç

Docker, "bende çalışıyordu" çağını kapatan ve modern yazılım geliştirmenin temel taşlarından biri haline gelen bir teknolojidir. Uygulamalarınızı taşınabilir, tutarlı ve verimli container'lar içinde paketleyerek hem geliştirme döngülerinizi hızlandırır hem de altyapı maliyetlerinizi düşürürsünüz. Doğru kurgulandığında containerizasyon; sürekli dağıtım, kolay ölçekleme ve dayanıklı sistemler için sağlam bir zemin oluşturur. Ancak bu zemini sağlam atmak; Dockerfile pratiklerinden güvenlik sertleştirmeye, orkestrasyon seçiminden izlemeye kadar bilgi ve deneyim ister.

KaliteliWebsite olarak İstanbul'dan tüm Türkiye'ye, container mimarisi tasarımı, mevcut uygulamaların Docker'a taşınması, CI/CD entegrasyonu ve production ortamında izleme konularında uçtan uca hizmet veriyoruz. Projelerinizi en başından container dostu, ölçeklenebilir ve güvenli mimarilerle kuruyoruz. 10.000 TL'den başlayan fiyatlarla ve ücretsiz keşif görüşmesiyle ihtiyaçlarınızı birlikte değerlendirip size en uygun yol haritasını çıkarıyoruz. Container yolculuğunuza sağlam bir başlangıç yapmak için bizimle iletişime geçin.

İlgili Yazılar