8 dk

Docker'ın Bulutta Güvenilir Uygulamaları Çalıştırmadaki Önemi

Docker'ın laptoptan buluta aynı uygulamayı çalıştırmayı nasıl kolaylaştırdığını, dağıtımları nasıl basitleştirdiğini, taşınabilirliği nasıl artırdığını ve ortam sorunlarını nasıl azalttığını öğrenin.

Docker'ın Bulutta Güvenilir Uygulamaları Çalıştırmadaki Önemi

Docker, bulut dağıtımları için neden bu kadar yardımcıdır

Çoğu bulut dağıtım sıkıntısı tanıdık bir sürprizle başlar: uygulama dizüstü bilgisayarda çalışıyor, ama bulut sunucusuna geçince bozuluyor. Belki sunucuda farklı bir Python veya Node sürümü vardır, eksik bir sistem kütüphanesi vardır, yapılandırma dosyası biraz farklıdır veya arka planda çalışması gereken bir servis çalışmıyordur. Bu küçük farklar birikir ve ekipler ürünü geliştirmek yerine ortamı hata ayıklamakla uğraşır.

Docker, basitçe açıklanmış hali

Docker, uygulamanızı çalıştırmak için gereken runtime ve bağımlılıkları birlikte paketleyerek yardımcı olur. “X sürümünü yükle, sonra Y kütüphanesini ekle, sonra bu konfigürasyonu ayarla” gibi adımlar göndermek yerine, bu parçaları zaten içeren bir container image gönderirsiniz.

Kullanışlı bir zihinsel model:

  • Image = paketlenmiş uygulama (çalıştırmak için gereken her şeyin anlık görüntüsü)
  • Container = o imajın çalışan örneği

Aynı imajı bulutta çalıştırdığınızda, yerelde test ettiğinizle aynı şeyi çalıştırmış olursunuz ve “ama sunucum farklı” problemleri büyük ölçüde azalır.

Kim fayda sağlar (ipucu: sadece geliştiriciler değil)

Docker farklı rollere farklı nedenlerle yardımcı olur:

  • Geliştiriciler öngörülebilir bir ortam ve daha hızlı onboarding elde eder ("bu container'ı çalıştır" çok sayfalı kurulum dokümanlarından daha iyidir).
  • Operasyon ve platform ekipleri daha tutarlı dağıtımlar ve uygulama-sunucu sınırları elde eder.
  • Küçük ekipler her proje için özel dağıtım scriptleri icat etmeden üretime tekrarlanabilir bir yol alır.
  • Kurumsal yapılar için standartlaşma: birçok ekip ve servis arasında aynı paketleme formatı.

Gerçekçi bir beklenti

Docker son derece yardımcıdır, ancak ihtiyaç duyacağınız tek araç değildir. Konfigürasyonu, gizli bilgileri, veri depolamayı, ağ yapılandırmasını, izlemeyi ve ölçeklemeyi yine yönetmeniz gerekir. Birçok ekip için Docker, yerel iş akışlar için Docker Compose ve üretim için orkestrasyon platformlarıyla birlikte çalışan bir yapı taşıdır.

Docker'ı uygulamanız için bir nakliye konteyneri olarak düşünün: teslimatı öngörülebilir hale getirir. Limanda (bulut kurulumu ve runtime) ne olduğu hâlâ önemlidir—ama her gönderim aynı şekilde paketlendiğinde iş çok daha kolaylaşır.

Docker temelleri: konteynerler, image'lar ve registry'ler

Docker yeni bir sözlüğe sahipmiş gibi gelebilir, ama temel fikir basittir: uygulamanızı her yerde aynı şekilde çalıştırılacak biçimde paketleyin.

Konteyner vs. sanal makine (VM)

Bir sanal makine, tam bir misafir işletim sistemi ve uygulamanızı birlikte paketler. Bu esnek ama çalıştırması daha ağır ve başlatması daha yavaştır.

Bir konteyner uygulamanızı ve bağımlılıklarını paketler, ancak host makinenin OS çekirdeğini paylaşır; tam bir işletim sistemi taşımak yerine. Bu yüzden konteynerler genellikle daha hafif olur, saniyeler içinde başlar ve aynı sunucuda daha fazla çalıştırılabilir.

Sürekli gördüğünüz ana terimler

Image: Uygulamanız için salt okunur bir şablon. Kodunuzu, runtime'ı, sistem kütüphanelerini ve varsayılan ayarları içeren paketlenmiş bir artefakt gibi düşünün.

Container: Bir image'ın çalışan örneği. Eğer image bir plan ise, container şu anda yaşadığınız ev gibidir.

Dockerfile: Bir image oluşturmak için Docker'ın kullandığı adım adım talimatlar (bağımlılık yükleme, dosya kopyalama, başlatma komutunu ayarlama).

Registry: Image'lerin saklandığı ve dağıtıldığı servis. Image'leri bir registry'e "push" eder ve sunucularda daha sonra "pull" edersiniz (halka açık registry'ler veya şirket içi özel registry'ler).

Standartlaşma neden önemli

Uygulamanız Dockerfile'dan oluşturulmuş bir image olarak tanımlandığında, teslim için standart bir birim elde edersiniz. Bu standartlaşma sürümleri tekrarlanabilir kılar: yerelde test ettiğiniz aynı image'i dağıtırsınız.

Ayrıca teslimleri devretmeyi basitleştirir. "Benim makinemde çalışıyor" demek yerine, registry'deki belirli bir image versiyonunu gösterip: bu container'ı şu ortam değişkenleriyle, şu portta çalıştırın diyebilirsiniz. Bu, geliştirme ve üretim ortamlarının tutarlılığı için temel oluşturur.

Dizüstü bilgisayardan buluta tutarlılık: temel fayda

Docker'ın bulut dağıtımlarında önem kazanmasının en büyük nedeni tutarlılıktır. Bir Dockerfile içinde ortamı bir kez tanımlayıp aşamalar arasında tekrar kullanırsınız; böylece dizüstü bilgisayarınızda, CI runner'da veya bulut VM'de ne yüklü olduğuna bağlı kalmazsınız.

"Tutarlı" olmak pratikte ne anlama gelir

Pratikte tutarlılık şunlar olarak görünür:

  • Geliştirme, test ve üretimde aynı runtime sürümleri (örneğin aynı Node/Python/JVM ve OS paketleri)
  • Daha az bağımlılık sürüm kayması sorunu (kütüphaneler, OS paketleri)
  • Kolay geri alma için önceki image tag'ini yeniden dağıtabilme
  • Daha net hata ayıklama çünkü ortamlar eşleşir

Bu tutarlılık hızlıca fayda sağlar. Üretimde görülen bir hatayı, aynı image tag'ini yerelde çalıştırarak yeniden üretebilirsiniz. Eksik bir kütüphane nedeniyle başarısız olan bir dağıtım da artık daha az olasıdır çünkü test container'ınızda da o kütüphane eksik olurdu.

"Aynı şeyleri sadece kur" yaklaşımından farkı nedir

Ekipler genellikle kurulum dokümanları veya sunucu yapılandırma script'leriyle standartlaşmaya çalışır. Sorun, zaman içinde makinelerin yamalar ve paket güncellemeleriyle değişmesi ve farkların yavaşça birikmesidir.

Docker ile ortam bir artefakt olarak ele alınır. Güncellemeniz gerektiğinde yeni bir image oluşturur ve onu dağıtırsınız—değişiklikler açık ve incelenebilir olur. Eğer güncelleme sorun yaratırsa, rollback genellikle önceki bilinen iyi tag'i dağıtmak kadar basittir.

Bulutlar ve sunucular arasında taşınabilirlik

Docker'ın bir diğer büyük kazanımı taşınabilirliktir. Bir container image uygulamanızı taşınabilir bir artefakta dönüştürür: bir kez oluşturun, sonra uyumlu bir container runtime olan her yerde çalıştırın.

Aynı image, farklı evler

Bir Docker image uygulama kodunuzu ve runtime bağımlılıklarını (ör. Node.js, Python paketleri, sistem kütüphaneleri) paketler. Bu, laptopunuzda çalıştırdığınız bir imajın aynı zamanda şunlarda da çalışabileceği anlamına gelir:

  • AWS, Azure veya Google Cloud üzerinde bir VM
  • Veri merkezinizdeki kendi sunucularınız
  • Kubernetes tabanlı yönetilen konteyner platformları

Bu, uygulama runtime düzeyinde tedarikçi kilitlenmesini azaltır. Bulut-native servisleri (veritabanları, kuyruklar, depolama) kullanmaya devam edebilirsiniz, ama çekirdek uygulamanız host değişti diye yeniden inşa edilmek zorunda kalmaz.

Registry'ler nerede devreye girer

Taşınabilirlik, image'lerin bir registry'de saklandığında ve sürümlendiğinde en iyi şekilde çalışır—halka açık veya özel. Tipik bir iş akışı şöyledir:

  1. Bir image bir kez oluşturulur (ör. myapp:1.4.2).
  2. Registry'e push edilir.
  3. Her ortamda aynı image pull edilip çalıştırılır.

Registry'ler ayrıca dağıtımları yeniden üretmeyi ve denetlemeyi kolaylaştırır: üretim 1.4.2 çalıştırıyorsa, aynı artefaktı daha sonra çekip tam olarak aynı bitlere erişebilirsiniz.

Pratik senaryolar

Host taşıma: Bir VM sağlayıcısından diğerine geçerseniz, yığın yeniden kurulmaz. Yeni sunucuyu registry'e yönlendirirsiniz, image'i pull eder ve aynı konfigürasyonla container'ı başlatırsınız.

Ölçeklendirme: Daha fazla kapasiteye mi ihtiyacınız var? Aynı image'den ek containerlar başlatın. Her örnek özdeş olduğu için ölçekleme tekrarlanabilir bir işlem olur, elle kurulum gerekmez.

Küçük, tekrarlanabilir ve sürdürülebilir image'ler oluşturma

İyi bir Docker image yalnızca "çalışan bir şey" değildir. Daha sonra yeniden oluşturabileceğiniz ve güvenebileceğiniz paketlenmiş, sürümlenmiş bir artefakttır. Bulut dağıtımlarını öngörülebilir kılan bu güvenilirdir.

Dockerfile: yapı tarifiniz

Bir Dockerfile, uygulama imajınızı adım adım nasıl monte edeceğinizi tanımlar—tam olarak hangi başlangıç imajı, hangi bağımlılıklar, hangi dosyaların kopyalanacağı ve uygulamayı hangi komutun başlatacağı gibi. Bu dosyanın temiz ve niyetli tutulması, imajın hata ayıklanmasını, incelenmesini ve bakımını kolaylaştırır.

İmajları ince ve tekrarlanabilir tutacak en iyi uygulamalar

Küçük image'ler daha hızlı çekilir, daha hızlı başlar ve kırılma ya da güvenlik açıkları içerebilecek fazla "şey" barındırmaz.

  • Uygun olduğunda küçük bir temel imaj seçin (örneğin alpine veya slim varyantları).
  • Temel imajlar ve ana paketler için sürüm sabitleyin. Yüzen sürümler beklenmedik değişikliklere yol açabilir.
  • Katmanları ve dosyaları minimize edin: ilgili komutları birleştirin ve paket önbelleklerini temizleyin ki geçici derleme artefaktları image'e dahil edilmesin.

Çok aşamalı (multi-stage) build'ler: büyükçe derle, küçükçe gönder

Birçok uygulama derleme araçlarına ihtiyaç duyar ama çalışmak için bunlara gerekmez. Multi-stage build'ler bir aşamada derleyip ikinci, minimal aşamada üretim için küçük bir imaj oluşturmanıza izin verir.

# build stage
FROM node:20 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# runtime stage
FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html

Sonuç, daha az yaması gereken daha küçük bir üretim imajıdır.

Etiketleme stratejisi: dağıtımları izlenebilir kılın

Tag'ler neyi dağıttığınızı tam olarak belirlemenin yoludur.

  • Üretimde latest'e güvenmeyin; belirsizdir.
  • Semantik sürümler kullanın (ör. 1.4.2)
  • Commit SHA tag'i ekleyin (ör. 1.4.2-<sha> veya sadece <sha>) ki bir imajı üreten koda her zaman izleyebilesiniz.

Bu, temiz geri almaları ve değişiklikler olduğunda net denetimleri destekler.

Gerçek uygulamaları çalıştırmak: ağ, konfigürasyon ve veri

Bulut kurulumunuzu planlayın
Dağıtımdan önce hizmetleri, portları, ortam değişkenlerini ve veri ihtiyaçlarını eşleyin.

Gerçek bir bulut uygulaması genellikle tek bir süreç değildir. Küçük bir sistemdir: bir web ön yüzü, bir API, belki bir arka plan worker ve bir veritabanı veya cache. Docker hem basit hem çok servisli düzenleri destekler—sadece container'ların nasıl iletişim kurduğunu, konfigürasyonun nerede durduğunu ve verinin nasıl yeniden başlatmalarda korunduğunu anlamanız gerekir.

Tek container vs. çoklu servis uygulamaları

Tek container'lı bir uygulama statik site veya bağımlılığı olmayan tek bir API olabilir. Tek bir portu açarsınız (ör. 8080) ve çalıştırırsınız.

Çok servisli uygulamalar daha yaygındır: web api'ye bağlıdır, api db'ye bağlıdır ve bir worker kuyruktan işler tüketir. IP adreslerini sabitlemek yerine, container'lar genellikle paylaşılan bir ağda servis adıyla iletişim kurar (ör. db:5432).

Yerel ve staging için Docker Compose

Docker Compose, tüm yığını bir komutla başlatmanızı sağladığı için yerel geliştirme ve staging için pratiktir. Ayrıca uygulamanızın "şekil"ini (servisler, portlar, bağımlılıklar) ekipçe paylaşılabilecek bir dosyada belgeler.

Tipik ilerleyiş:

  • Yerelde Compose (hızlı geri bildirim)
  • Staging VM'de Compose (prodaya yakın davranış)
  • Üretimde bir bulut runtime/orkestratör

Konfigürasyon: image içinde ne olmamalı

Image'ler yeniden kullanılabilir ve paylaşılması güvenli olmalıdır. Ortama özgü ayarları image dışında tutun:

  • Gizli bilgiler (API anahtarları, DB parolaları)
  • Staging ve prod arasında farklı olan URL'ler
  • Feature flag'ler

Bunları ortam değişkenleri, bir .env dosyası (dikkat: commit etmeyin) veya bulutunuzun secrets manager'ı aracılığıyla iletin.

Volumes ile veriyi korumak

Container'lar geçicidir; veriniz olmamalı. Yeniden başlatmalarda kalması gereken her şey için volume kullanın:

  • Veritabanları (Postgres, MySQL)
  • Kullanıcı yüklemeleri
  • Kolay yeniden oluşturulamayacak üretilmiş dosyalar

Bulut dağıtımlarında eşdeğer şey yönetilen depolamadır (managed DB, network diskleri, object storage). Önemli fikir: container'lar uygulamayı çalıştırır; kalıcı depolama durumu korur.

Dağıtım iş akışları: build'den bulutta çalıştırmaya

Sağlıklı bir Docker dağıtım iş akışı kasıtlı olarak basittir: bir image oluşturun ve aynı image'i her yerde çalıştırın. Dosyaları sunuculara kopyalamak veya kurucuları yeniden çalıştırmak yerine dağıtımı tekrarlanabilir bir rutine çevirirsiniz: image'i pull et, container'ı çalıştır.

Temel akış: build → push → run

Çoğu ekip şu pipeline'ı takip eder:

  1. Sürümlenmiş bir image oluşturun (ör. myapp:1.8.3).
  2. Bunu bir registry'e push edin (Docker Hub, bulut registry'si veya özel bir registry).
  3. Bulut ortamında o exact image'i pull edip container'ları başlatın.

Son adım Docker'ı iyi anlamlı bir şekilde "sıkıcı" yapar:

# build locally or in CI
docker build -t registry.example.com/myapp:1.8.3 .

docker push registry.example.com/myapp:1.8.3

# on the server / cloud runner
docker pull registry.example.com/myapp:1.8.3

docker run -d --name myapp -p 80:8080 registry.example.com/myapp:1.8.3

Yaygın bulut desenleri

İki yaygın yol:

  • VM + Docker: bir sanal makineyi yönetirsiniz, Docker kurar ve container'ları kendiniz çalıştırırsınız. Basittir ve küçük kurulumlar için harikadır.
  • Yönetilen konteyner servisleri: bulut sağlayıcı container host'larını sizin için çalıştırır. Hâlâ aynı image'i dağıtırsınız, ama ölçekleme, yeniden başlatma ve ağ daha otomatik olur.

Kesintisiz dağıtım temelleri

Sürümler sırasında aksaklıkları azaltmak için üretimde genellikle üç yapı taşı kullanılır:

  • Sağlık kontrolleri: bir container'ın gerçekten hazır olduğunu doğrular (sadece "başladı" demesi yeterli değil).
  • Rolling update'ler: container'ları hepsini birden değil kademeli olarak değiştirin.
  • Load balancer'lar: yalnızca sağlıklı container'lara trafik yönlendirir ve yükü dağıtır.

Registry'ler ve ortamlar arasında image promosyonu

Registry sadece depolama değildir—ortamları tutarlı tutmanın yoludur. Yaygın bir uygulama aynı image'i dev → staging → prod arasında promote etmek (genellikle yeniden tag'leyerek) ve her seferinde yeniden inşa etmemektir. Böylece üretim, test ettiğiniz tam artefaktı çalıştırır ve "staging'te çalışıyordu" sürprizleri azalır.

Docker ile CI/CD: daha hızlı, daha temiz sürümler

Build'lerinizi öngörülebilir hale getirin
Tutarlı bir ortamda build edin ve test edin, sonra aynı artifact'i ilerletin.

CI/CD temel olarak yazılımı gönderme hattıdır. Docker, her adımın bilinen bir ortamda çalışmasını sağladığından bu hattı daha öngörülebilir kılar.

Docker pipeline'da nerede yer alır

Docker dostu bir pipeline genellikle üç aşama içerir:

  • Build: kodunuzdan sürümlenmiş bir Docker image oluşturun (ör. myapp:1.8.3).
  • Test: otomatik testleri container içinde çalıştırın ki tooling ve bağımlılıklar ileride çalışacakla eşleşsin.
  • Publish: image'i registry'e push edin ki diğer ortamlar aynı artefaktı çekebilsin.

Bu akış teknik olmayan paydaşlara da kolayca anlatılabilir: "Bir kutuyu kapatıyoruz, kutuyu test ediyoruz, sonra aynı kutuyu her ortama gönderiyoruz."

Üretimin sürpriz olmaması için testleri container içinde çalıştırma

Testler genellikle yerelde geçer ama üretimde başarısız olur çünkü runtime farklıdır, sistem kütüphaneleri eksiktir veya farklı ortam değişkenleri vardır. Testleri container içinde çalıştırmak bu boşlukları azaltır. CI runner'ınızın dikkatlice ayarlanmış bir makineye ihtiyacı yok—sadece Docker olması yeterlidir.

Artefakt promosyonu: dev → staging → prod

Docker "promote, yeniden inşa etme" modelini destekler. İşlem şöyledir:

  1. myapp:1.8.3'ü bir kez oluşturun ve test edin.
  2. Aynı image'i dev'e konuşlandırın.
  3. İyi görünürse aynı image'i staging'e deploy edin.
  4. Son olarak aynı image'i üretime gönderin.

Ortamlar arasında sadece konfigürasyon değişir (URL'ler veya kimlik bilgileri gibi), uygulama artefaktı değişmez. Bu, sürüm günü belirsizliklerini azaltır ve geri almayı basitleştirir: önceki image tag'i tekrar dağıtılır.

Koder.ai nerede yardımcı olabilir

Hızlı hareket ediyorsanız ve Docker faydalarını günlerce alt yapı kurmadan almak istiyorsanız, Koder.ai sohbet odaklı bir iş akışından üretime uygun bir uygulama oluşturup onu temizce konteynerleştirmede yardımcı olabilir.

Örneğin ekipler sıklıkla Koder.ai'ı şunlar için kullanır:

  • React ön yüzü artı Go backend ve PostgreSQL oluşturmak,
  • erken aşamada bir Dockerfile ve docker-compose.yml eklemek (böylece dev ve prod davranışı uyumlu kalır),
  • tam kaynak kodunu dışa aktarıp standart bir build → push → run hattına bağlamak,
  • yineleme sırasında anlık görüntüler ve rollback kullanmak ki dağıtım değişiklikleri kontrol altında kalsın.

Temel avantaj, Docker'ın dağıtım ilkesinin korunmasıdır; Koder.ai fikirden konteyner-e hazır kod tabanına giden yolu hızlandırır.

Bir sunucudan öteye ölçeklenme: Docker ve orkestrasyon

Docker bir servisi tek bir makinada paketlemeyi ve çalıştırmayı kolaylaştırır. Ancak birden fazla servis, her servisten birden fazla kopya ve birden fazla sunucu olduğunda her şeyi koordine eden bir sisteme ihtiyacınız olur. Orkestrasyon, container'ların nerede çalışacağını belirleyen, onları sağlıklı tutan ve talep değiştikçe kapasiteyi ayarlayan yazılımdır.

Birçok container ile neden orkestrasyon gerekir

Birkaç container ile işleri elle yönetebilirsiniz; ancak ölçek büyüdüğünde bu yaklaşım hızla yetersiz kalır:

  • Bir sunucu arızalanabilir ve içindeki birkaç container ile birlikte gider.
  • Trafiğe göre bir web servisini 2, 10 veya 100 kopyaya çıkarmanız gerekebilir.
  • Güncellemeler uygulamayı çevrimdışı bırakmadan dağıtılmalıdır.
  • Servislerin birbirini bulması (service discovery) ve konfigürasyon paylaşımı için tutarlı bir yol gerekir.

Kubernetes, ağır jargon olmadan açıklama

Kubernetes (kısaca K8s) en yaygın orkestratördür. Basit bir zihinsel model:

  • Nodes: container'ları çalıştıran makineler (VM veya fiziksel).
  • Pods: Kubernetes'in çalıştırdığı en küçük birim (genelde bir container, bazen birlikte yaşaması gereken birkaç container).
  • Deployments: bu pod'dan N tane çalıştır ve o sayıyı koru, rolling update'leri içerebilir.
  • Services: diğer parçaların bu pod'lara güvenilir şekilde ulaşmasını sağlayan sabit ağ noktaları.

Docker image'leri Kubernetes'e nasıl uyuyor

Kubernetes image oluşturmaz; onları çalıştırır. Siz hâlâ bir Docker image oluşturur, registry'e push edersiniz; Kubernetes o image'i node'lara çeker ve container'ları başlatır. Image hâlâ her yerde kullanılan taşınabilir, sürümlenmiş artefakttır.

Basit bir seçenek ne zaman yeterli olur

Eğer tek bir sunucuda birkaç servis varsa, Docker Compose çoğu durumda yeterli olabilir. Orkestrasyon, yüksek erişilebilirlik, sık dağıtımlar, otomatik ölçekleme veya kapasite ve dayanıklılık için birden fazla sunucu gerektiğinde değer kazanmaya başlar.

Konteynerler için güvenlik ve uyumluluk temelleri

Konteynerler uygulamayı sihirli şekilde güvenli hale getirmez—ancak standartlaştırma ve otomasyon yoluyla zaten yapılması gereken güvenlik çalışmalarını uygulamayı kolaylaştırır. Artısı, Docker size denetçiler ve güvenlik ekiplerinin önem verdiği kontrolleri ekleyebileceğiniz tekrarlanabilir noktalar verir.

Image taraması (neden önemli)

Bir container image uygulamanızla birlikte bağımlılıkları da paketlediği için güvenlik açıkları genellikle temel imajlardan veya sizin yazmadığınız sistem paketlerinden gelir. Image taraması, üretime göndermeden önce bilinen CVE'leri kontrol eder.

Taramayı pipeline'da bir kapı haline getirin: kritik bir açıklık bulunursa build'i başarısız kılın ve yamalı bir temel imajla yeniden oluşturun. Tarama sonuçlarını artefakt olarak saklayın ki denetimlerde ne gönderildiğini gösterebilesiniz.

Varsayılan olarak en az ayrıcalık (least privilege)

Mümkün olduğunda non-root kullanıcı ile çalıştırın. Birçok saldırı, container içinde root erişimi üzerinden kaçma veya dosya sistemi üzerinde değişiklik yapma üzerine kuruludur.

Ayrıca konteyner için salt okunur dosya sistemi ve sadece belirli yazılabilir yolları mount etmeyi düşünün (loglar veya yüklemeler için). Bu, bir saldırgan içeri girerse değiştirebileceklerini sınırlar.

Gizlilik anahtarları: sırları image'e koymayın

Asla API anahtarlarını, parolaları veya özel sertifikaları Docker image'inize kopyalamayın veya Git'e commit etmeyin. Image'ler önbelleğe alınır, paylaşılır ve registry'lere push edilir—gizli bilgiler genişçe sızabilir.

Bunun yerine gizli bilgileri runtime'ta platformunuzun secret store'u ile enjekte edin (ör. Kubernetes Secrets veya bulut sağlayıcınızın secrets manager'ı) ve yalnızca gerekli servislere erişim izni verin.

Güncellemeler ve yama: düzenli yeniden build edin

Geleneksel sunucuların aksine container'lar çalışırken kendilerini yamalamaz. Standart yaklaşım: bağımlılıkları güncellenmiş bir image oluşturup yeniden dağıtmak.

Bir takvim belirleyin (haftalık veya aylık) even app kodu değişmemiş olsa bile image'leri yeniden build edin; yüksek önem derecesi taşıyan CVE'ler temel imajı etkilediğinde derhal yeniden build edin. Bu alışkanlık dağıtımları denetlemeyi ve riski azaltmayı kolaylaştırır.

Sık yapılan hatalar ve nasıl önlenir

Öğrenerek oluşturun
Rehberli bir sohbet akışı ile servisleri, konfigürasyonları ve Docker kurulumunu yineleyin.

Docker "kullanılıyor" olsa bile birkaç alışkanlık problemlere yol açabilir. İşte en çok ağrı veren hatalar ve pratik önlemler.

1) Container'ları evcil hayvan gibi görmek (üretimde elle değişiklikler)

Yaygın bir anti-pattern, sunucuya SSH ile girip bir şeyi elden düzeltmek veya çalışan container içine exec ile girip konfigürasyonu anında değiştirmektir. Bir kerede işe yarar, sonra tekrar bozulur çünkü o tam durumu kimse yeniden üretemez.

Bunun yerine container'ları sığır gibi davranın: geçici ve yerine konulabilir. Her değişikliği image build ve dağıtım pipeline'ı üzerinden yapın. Debug gerekiyorsa geçici bir ortamda yapın ve sonra düzeltmeyi Dockerfile, konfigürasyon veya altyapı ayarlarına kodlayın.

2) Dağınık Dockerfile'dan kaynaklı büyük image'ler ve yavaş build'ler

Devasa image'ler CI/CD'yi yavaşlatır, depolama maliyetlerini artırır ve güvenlik yüzeyini genişletir.

Bunu önlemek için Dockerfile yapınızı sıkılaştırın:

  • Mümkünse daha küçük bir temel imaj kullanın.
  • Bağımlılık dosyalarını önce kopyalayın (build cache için), sonra uygulama kodunu kopyalayın.
  • Derlenen uygulamalar için multi-stage build kullanın.
  • .dockerignore ekleyin ki node_modules, build artefaktları veya yerel gizlilikler image'e dahil olmasın.

Amaç, temiz ve hızlı yeniden üretilebilir bir build sağlamak.

3) Log ve metrikleri yok saymak (gözlemlenebilirlik hâlâ önemli)

Konteynerler uygulamanın ne yaptığını anlamayı gereksiz kılmaz. Loglar, metrikler ve izler yoksa sorunları sadece kullanıcı şikayetleriyle fark edersiniz.

En azından uygulamanızın stdout/stderr'e log yazdığından (yerel dosyalara değil), temel sağlık endpoint'leri olduğundan ve birkaç anahtar metriği (hata oranı, gecikme, kuyruk derinliği) yayınladığından emin olun. Sonra bu sinyalleri bulut stack'inizin izleme araçlarına bağlayın.

4) Stateful servisleri erken planlamamak (veritabanları, kuyruklar, dosyalar)

Durumsuz container'lar kolayca değiştirilir; durumlu veri ise değil. Ekipler genellikle veritabanını container içinde çalıştırmanın "iyi çalıştığını" görürler ama bir yeniden başlatma verileri sildiğinde sorunla karşılaşırlar.

Başından itibaren durumu nerede tutacağınıza karar verin:

  • Mümkünse yönetilen veritabanları/kuyruklar kullanın.
  • Kendi başınıza stateful servis çalıştırıyorsanız depolamayı, yedeklemeleri ve yükseltmeleri baştan tasarlayın.

Docker uygulamaları paketlemek için mükemmeldir—ama güvenilirlik, bu container'ların nasıl oluşturulduğu, gözlemlendiği ve kalıcı veriye nasıl bağlandığı konusunda kasıtlı olmaktan gelir.

Pratik başlarken kontrol listesi

Docker'a yeniyseniz, değeri hızlı almak için tek bir gerçek servisi uçtan uca konteynerleştirin: build edin, yerelde çalıştırın, registry'e push edin ve deploy edin. Kapsamı küçük tutmak ve sonuçları kullanılabilir yapmak için bu kontrol listesini kullanın.

1) Bir hizmetle başlayın (uçtan uca)

İlk olarak tek, durumsuz bir servis seçin (bir API, bir worker veya basit bir web uygulaması). Başlaması için ne gerektiğini tanımlayın: dinlediği port, gerekli ortam değişkenleri ve harici bağımlılıklar (ör. ayrı çalıştırabileceğiniz bir veritabanı).

Hedefi net tutun: "Aynı image ile yerelde ve bulutta aynı uygulamayı çalıştırabilmek."

2) Minimal bir Dockerfile + Compose oluşturun

Uygulamanızı güvenilir şekilde build edip çalıştırabilecek en küçük Dockerfile'ı yazın. Tercihler:

  • Küçük bir temel imaj
  • Sadece gerekenleri kopyalamak
  • Açık bir başlatma komutu

Sonra yerel geliştirme için hizmetleri ve ortam değişkenlerini bağlayan bir docker-compose.yml ekleyin (laptopa Docker dışında bir şey kurmadan). İleride daha derin yerel kurulum isterseniz genişletebilirsiniz—önce basit başlayın.

3) Bir registry ve etiketleme kuralı seçin

Image'lerin nerede duracağını seçin (Docker Hub, GHCR, ECR, GCR vb.). Sonra dağıtımları öngörülebilir kılacak tag'ler benimseyin:

  • :dev yerel test için (opsiyonel)
  • :git-sha (değiştirilemez, dağıtımlar için en iyisi)
  • :v1.2.3 sürümler için

Üretimde :latest kullanmaktan kaçının.

4) Otomatik build + publish için CI ekleyin

Her merge olduğunda image'i build edip registry'e push eden bir CI kurun. Pipeline'ın şu adımları içermesi iyi:

  1. Image'i build et
  2. Temel bir kontrol çalıştır (testler veya smoke run)
  3. Kararlaştırılan tag'lerle push et

Bunlar çalışınca, yayımlanan image'i bulut deploy adımına bağlayıp oradan yinelemeye başlayabilirsiniz.

SSS

Docker bulut dağıtımlarını neden daha güvenilir kılar?

Docker, uygulamanızı çalışması için gereken runtime ve bağımlılıklarla birlikte paketleyerek “makinemde çalışıyor” sorunlarını azaltır. Aynı görüntüyü (image) yerelde, CI’da ve bulutta çalıştırırsınız; böylece işletim sistemi paketleri, dil sürümleri ve yüklü kütüphanelerdeki farklar davranışı gizlice değiştirmez.

Docker image ile container arasındaki fark nedir?
  • Image: uygulamanız + runtime + bağımlılıkların okunur-yazılmaz, sürümlenmiş paketi.
  • Container: o image'dan çalışan örnek.

Genellikle bir image bir kez (ör. myapp:1.8.3) üretilir ve farklı ortamlarda bu image'dan birçok container çalıştırılır.

Konteyner bir sanal makineden (VM) nasıl farklıdır?

Bir sanal makine (VM) tam bir misafir işletim sistemi ile birlikte gelir; bu yüzden daha ağırdır ve başlatması genellikle daha yavaştır. Bir konteyner ise host makinenin çekirdeğini paylaşır ve yalnızca uygulamanın ihtiyaç duyduğu runtime ve kütüphaneleri taşır. Bu nedenle konteynerler genellikle:

  • daha hızlı başlar
  • CPU/RAM/disk açısından daha hafiftir
  • aynı sunucuda daha fazla kopya çalıştırmaya elverişlidir
Docker registry nedir ve neden gereklidir?

Registry, image'lerin saklandığı ve sürümlendiği yerdir; diğer makinelerin bu image'leri çekip çalıştırabilmesi için gereklidir.

Yaygın bir iş akışı:

  1. docker build -t myapp:1.8.3 .
  2. docker push <registry>/myapp:1.8.3
  3. Bulut bu kesin tag'i çekip çalıştırır

Bu yaklaşım geri almayı da kolaylaştırır: önceki bir tag'i yeniden dağıtabilirsiniz.

Üretim için iyi bir image etiketleme stratejisi nedir?

Üretimde ne çalıştığını her zaman tanımlayabilmek için değiştirilemez, izlenebilir tag'ler kullanın.

Pratik yaklaşım:

  • sürüm tag'leri: :1.8.3
  • build kimlikleri: :<git-sha>
  • üretimde :latest kullanmaktan kaçının (belirsizdir)

Bu, temiz geri almaları ve denetimleri destekler.

Docker ile gizli bilgileri ve konfigürasyonu nasıl yönetmeliyim?

Ortama özgü ayarları image'in dışına koyun. API anahtarlarını, parolaları veya özel sertifikaları Dockerfile içine kopyalamayın.

Bunun yerine:

  • konfigürasyonu ortam değişkenleriyle verin
  • bir secrets manager kullanın (bulut veya orkestrasyon platformu)
  • .env dosyalarını Git'e eklemeyin

Böylece image'ler yeniden kullanılabilir ve bilgilerin sızması azalır.

Konteynerler yeniden başlatılıp değiştirilebilirken veriyi nasıl kalıcı tutarım?

Konteynerler geçicidir; dosya sistemi yeniden başlatıldığında veya container yeniden oluşturulduğunda değişebilir. Kalıcı olması gereken veriler için:

  • volumes kullanın (veritabanları, yüklemeler)
  • mümkünse yönetilen bulut servislerini (managed DB, object storage) tercih edin

Kural: uygulamaları konteynerlerde çalıştırın, durumu amaçlanmış depolamada tutun.

Docker Compose ile Kubernetes arasında ne zaman tercih yapmalıyım?

Compose, yerel geliştirme veya tek host için çok uygundur:

  • tüm yığını tek komutla başlatırsınız
  • servis isimleriyle kolay ağ iletişimi sağlar (ör. db:5432)
  • yeni geliştiriciler için tutarlı onboarding sunar

Çok sunuculu, yüksek erişilebilirlik ve otomatik ölçekleme gereken üretim ortamları için genellikle bir orkestratör (çoğunlukla Kubernetes) kullanılır.

Docker ile basit bir CI/CD iş akışı nasıl görünür?

Pratik bir pipeline: build → test → publish → deploy

  • CI'da sürümlenmiş bir image oluşturun
  • testleri container içinde çalıştırın (üretime daha yakın)
  • image'i registry'e push edin
  • aynı image'i her ortamda pull edip çalıştırarak dağıtın

“Promote, rebuild yapma” yaklaşımını tercih edin (aynı artifact'i dev → staging → prod'a ilerletin).

Konteyner yerelde çalışırken bulutta neden başarısız olur?

Sık görülen nedenler:

  • Yanlış port eşlemesi: uygulamanın dinlediği container port'unu dışarıya açtığınızdan emin olun (ör. -p 80:8080).
  • Eksik ortam değişkenleri: aynı env değişkenlerini yerelde de kullanarak prod konfigürasyonunu tekrar edin.
  • Bağımlılık sürüm farkları: sürümlenmiş image'ler oluşturun ve host paketlerine güvenmeyin.
  • Sağlık kontrollerinin yokluğu: readiness/health endpoint'leri ekleyin ki rollout'lar erken trafik göndermesin.

Hata ayıklamak için prod tag'ini yerelde çalıştırıp konfigürasyonu karşılaştırmak iyi bir ilk adımdır.

Related posts