SSD Nodes Learn 8GB RAM — yılda $66
Rehberler Matt ConnorYazan Matt Connor · Güncellendi 2026-08-01

Docker Compose Ağ İletişimi Nasıl Çalışır?

Compose varsayılan bridge ağını, servis adıyla DNS erişimini, host modunu, projeler arası ortak ağı ve UFW'yi atlayan published port davranışını açıklar.

Uygulamanız başlamadan önce Compose ne oluşturur

Docker Compose ağ iletişimi tek bir kuralla başlar: docker compose up proje için özel bir ağ oluşturur, tüm servisleri bu ağa bağlar ve bu servislerin birbirine servis adıyla erişmesini sağlar. Bunun için tek bir networks: satırı yazılması gerekmez. Compose ağ iletişimindeki karışıklıkların çoğu, varsayılan ayarın zaten mevcut olduğunun bilinmemesinden kaynaklanır.

Küçük bir dosya aşağıdadır. Bu dosya shop adlı bir dizinde compose.yaml olarak kaydedilmelidir.

services:
  web:
    image: nginx:1.27
    ports:
      - "8080:80"
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: example

Projeyi başlatın ve Docker'ın oluşturduklarını inceleyin:

docker compose up -d
docker network ls

Listede artık shop_default adlı bir ağ bulunur. Compose bu ağı <project>_default olarak adlandırır ve proje adı varsayılan olarak dizin adının küçük harfli biçimidir. Bu adı docker compose -p myproject up -d ile veya dosyada üst düzey bir name: myproject tanımlayarak geçersiz kılabilirsiniz. Ağın sürücüsü bridge değeridir. Bu sürücü, ana bilgisayarın içindeki sanal bir anahtardır. Her kapsayıcı özel bir alt ağdan bir adres alır. Giden ağ trafiği dışarı çıkarken ana bilgisayarın adresine çevrilir.

docker compose down bu ağı yeniden siler. Eski bir projeden kalan kapsayıcının ağı açık tutabilmesinin nedeni budur: Docker error while removing network: network shop_default has active endpoints hatasıyla işlemi reddeder. Çözüm, ağa hâlâ bağlı olan kapsayıcının durdurulması veya kaldırılmasıdır.

Compose sizin için yeniyse, Compose dosyası düzeni ve yaşam döngüsü komutları konusunun önce okunması yararlı olur. Aşağıdaki tüm işlemler bir projeyi başlatıp durdurabildiğiniz varsayımına dayanır.

DNS hizmet adı üzerinden erişim, yeni başlayanların gözden kaçırdığı noktadır

Kullanıcı tanımlı herhangi bir ağda Docker, her kapsayıcının 127.0.0.11 üzerinden gördüğü yerleşik bir DNS sunucusu çalıştırır. Bu sunucu, hizmet adlarını geçerli kapsayıcı adreslerine çözümler. Bu nedenle web, hiçbir yapılandırma gerektirmeden veritabanına db ana bilgisayar adı ve 5432 bağlantı noktası üzerinden ulaşır.

docker compose exec web getent hosts db

Bu komut 172.18.0.2 db benzeri bir satır yazdırır. Hiçbir çıktı alınmazsa iki hizmet aynı ağda değildir.

Neredeyse herkesin bir kez yaptığı hata, uygulama yapılandırmasında localhost kullanmaktır. Bir kapsayıcının içinde localhost, ana bilgisayarı veya diğer hizmeti değil, söz konusu kapsayıcıyı ifade eder. Postgres istemcileri bunu açıkça bildirir:

could not connect to server: Connection refused
	Is the server running on host "localhost" (127.0.0.1) and accepting
	TCP connections on port 5432?

Bağlantı dizesi postgresql://postgres:example@db:5432/postgres olmalıdır. Ana bilgisayar bölümü, hizmet adıdır.

Daha sonra zaman kazandıran iki ayrıntı vardır. Adlar o anda çalışan kapsayıcıya çözümlenir. Bu nedenle docker compose up -d --scale web=3, tek bir adla üç adres döndürebilir. DNS önbelleğini sonsuza kadar saklayan istemci ise kendisini artık çalışmayan bir kapsayıcıya sabitler. Ayrıca --network olmadan kullanılan düz docker run komutunun oluşturduğu eski bridge ağında ad çözümlemesi hiç yoktur. Bu nedenle 2016 tarihli kapsayıcı bağlantıları hakkındaki öneriler, görülen davranışla örtüşmez.

İki hizmeti birbirine bağlamak için ports: gerekmez

ports:, bir container portunu ana makinede yayımlar. Docker dışından gelen ağ trafiği içindir. Proje ağında port aralığının tamamı üzerinden zaten çalışan hizmetler arası trafikle ilgisi yoktur.

Bu nedenle birçok kişinin veritabanı hizmetine eklediği ports: - "5432:5432" hiçbir yarar sağlamaz ve gerçek bir güvenlik riski oluşturur: Postgres'i sunucunun herkese açık arayüzünde erişilebilir hale getirir. Bunu silin. Bir geçiş işlemi için dizüstü bilgisayarınızdan erişilmesi gerekiyorsa, "127.0.0.1:5432:5432" ile loopback adresine bağlayın ve bir SSH tüneli üzerinden erişin. Dinleme soketi, yayımlanmış port ve firewall kuralı arasındaki fark, Linux'ta portların ve dinleyen hizmetlerin çalışma şekli bölümünde açıklanmaktadır.

expose:, Compose kapsamında yalnızca belgelendirme amaçlıdır. Aynı ağdaki container'lar arasında hiçbir şey kapatılmadığı için herhangi bir portu açmaz.

network_mode host ne zaman kullanılmalı ve maliyeti nedir

Host modu, container'ın kendi network namespace'ini kaldırır ve işlemin doğrudan host'un arayüzlerini kullanmasını sağlar.

services:
  probe:
    image: alpine:3.20
    network_mode: host
    command: sleep infinity

Bunu tercih etmek için geçerli nedenler vardır. Yerel ağdaki broadcast veya multicast trafiğini görmesi gereken bir işlem, bridge arkasından bu trafiği göremez. Bunun nedeni, bridge'in bu trafiği container'a iletmemesidir. Örneğin bir media server için cihaz keşfi veya bir home automation hub için ağ keşfi buna dahildir. Host'un arayüz sayaçlarını okuyan bir monitoring agent, host'un arayüzlerine ihtiyaç duyar. Ayrıca address translation adımı atlanır. Bu, yüksek paket hızlarında önemlidir.

Maliyetleri belirgindir.

ports: çalışmaz. Docker, host network mode kullanıldığında yayınlanan portların yok sayıldığı konusunda uyarı verir. Container, işlemin bağlandığı portlara bağlanır. 8080 portunu kullanmak isteyen iki host mode container çakışır ve ikincisi bind: address already in use ile sonlanır.

Service name ile name resolution her iki yönde de kullanılamaz. Container, project network üzerinde değildir. Bu nedenle db çözümlenemez ve diğer servisler de container'ı çözümleyemez. Bu servislere yalnızca host üzerinde yayınlanan portlar üzerinden, genellikle 127.0.0.1 adresinde ulaşır.

Isolation ortadan kalkar. Host mode container içindeki bir işlem 0.0.0.0 adresine bağlanırsa server'ınızın tüm arayüzlerini, public arayüz dahil, apt ile kurulmuş bir package gibi dinler. Bunun bir avantajı vardır: Bu trafik normal input yolunu izler. Bu nedenle UFW kuralları uygulanır. Published port'larda ise bu geçerli değildir.

Host mode, Linux Docker Engine özelliğidir. Docker Desktop bu özelliği yalnızca 4.34 sürümünden itibaren ve etkinleştirildikten sonra destekler. Ayrıca container'lar host IP adreslerine bağlanamaz ve yalnızca TCP ile UDP işlenir. Ekibinizin bir bölümü Linux server'larda, diğer bölümü Docker Desktop üzerinde çalışıyorsa aynı dosyanın farklı davranmasını bekleyin.

Host'un arayüzlerine ihtiyaç duyulduğunda host mode kullanılmalıdır. Bir bağlantı sorununu düzeltmek için kullanılmamalıdır. Çünkü genellikle bir sorunu daha zor bir sorunla değiştirir.

İki Compose projesini harici bir ağ ile bağlama

Bir proje tarafından oluşturulan ağ başka bir proje tarafından görünmez. Bu nedenle proxy/compose.yaml içindeki ters proxy, aynı sunucuda olsa bile app/compose.yaml içindeki uygulamayı göremez. Çözüm, hiçbir projenin sahip olmadığı bir ağ kullanmaktır.

Bu ağı bir kez el ile oluşturun:

docker network create edge

Ardından her projede harici ağ olarak tanımlayın. Proxy tarafı:

services:
  proxy:
    image: traefik:v3.1
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - edge

networks:
  edge:
    name: edge
    external: true

Uygulama tarafı:

services:
  app:
    image: nginx:1.27
    networks:
      - edge
      - internal
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: example
    networks:
      - internal

networks:
  edge:
    name: edge
    external: true
  internal:

external: true, Compose'a yeni bir ağ oluşturmak yerine mevcut bir ağa bağlanmasını ve ağı docker compose down üzerinde olduğu gibi bırakmasını bildirir. Ayrı name: anahtarı göründüğünden daha önemlidir: bu anahtar olmadan Compose, tam olarak edge adında bir ağ arar. Bu anahtar sayesinde ağın dosyanızdaki adını, ana bilgisayardaki adından farklı belirleyebilirsiniz.

Ağ mevcut değilse Compose başlatmayı reddeder ve ağın harici olarak tanımlandığını ancak bulunamadığını bildirir. Önce ağı oluşturun.

Uygulama dosyasının internal ile ne yaptığına dikkat edin. Veritabanı yalnızca o projeye ait yerel ağda bulunur. Bu nedenle proxy veritabanına erişemez ve yalnızca app erişebilir. Bir ağın altına internal: true eklemek, veritabanının dış dünyaya giden rotasını da tamamen kaldırır. Bu, veritabanı için iyi bir varsayılandır. Ancak etkinleştirmeden önce bilinmesi gereken bir maliyeti vardır: dahili bir ağdaki container hiçbir şey indiremez. Bu nedenle başlangıçta apt-get update veya pip install çalıştıran bir entrypoint asılır ve ardından zaman aşımı hatasıyla başarısız olur.

Yönlendirme kuralları ve sertifikalarla birlikte eksiksiz bir kurulum için tek bir Traefik instance arkasında birden çok uygulama çalıştırma bölümüne bakın.

UFW kurallarını aşan yayımlanmış portlar

Compose ağ yapılandırmasının güvenlik olayına dönüştüğü bölüm budur. Bir port yayımlanır, UFW'nin etkin olduğu ve SSH dışındaki her şeyi reddettiği doğrulanır, ancak hizmet internete açık kalır.

sudo ufw status
curl http://203.0.113.10:8080

UFW portun engellendiğini belirtir. curl yine de sayfayı döndürür. Burada bir arıza yoktur. Docker, kendi adres çevirme ve yönlendirme kurallarını doğrudan iptables içine yazar. Yayımlanmış bir container portuna gelen trafik host'a teslim edilmek yerine container'a yönlendirilir. Bu nedenle trafik, UFW'nin yerel hedefli trafik için yönettiği zincirden geçmez. Docker kuralları da UFW kurallarından önce eşleştirilir.

Kısa çözüm, yalnızca gerektiği yerde yayımlamaktır:

    ports:
      - "127.0.0.1:8080:80"

Bu işlem host tarafını loopback'e bağlar. Böylece porta sunucunun kendisinden ve bir SSH tüneli üzerinden erişilebilir; başka hiçbir yerden erişilemez. Genel erişim giriş noktasını, 80 ve 443 portlarını bilerek yayımlayan bir reverse proxy'nin arkasına yerleştirin. Yayımlanmış bir portu filtrelemeniz gereken durumlar için DOCKER-USER zincirini de içeren ayrıntılı açıklama, Docker'ın neden UFW'yi doğrudan aştığı ve bunun nasıl düzeltileceği bölümünde yer alır.

Dört komutla nasıl hata ayıklanır

Önce her container'ın gerçekte hangi network üzerinde olduğunu kontrol edin:

docker network inspect shop_default

Containers bloğunda, bağlı tüm container'lar adresleriyle listelenir. Bu listede bulunmayan bir service farklı bir network üzerindedir, host mode kullanıyordur veya çalışmıyordur.

Kendi image'larınızın içinde herhangi bir araç kullanmanız gerekmemesi için, aynı network'e bağlı geçici bir container'dan name resolution işlemini test edin:

docker run --rm --network shop_default busybox nslookup db
docker run --rm --network shop_default busybox nc -zv db 5432

nslookup başarısız olursa sorun name resolution veya network üyeliğindedir. nslookup başarılı olurken nc başarısız oluyorsa service çalışıyor, ancak bu port üzerinde listening yapmıyordur veya kendi container'ı içinde 127.0.0.1 üzerinde listening yapıyordur; 0.0.0.0 üzerinde değil. Bu durum development server'larda yaygındır. Çözüm Docker'da değil, uygulamanın bind address ayarındadır.

Docker hatası gibi görünen bir başka arıza da vardır. Container'lar birbiriyle iletişim kurabiliyor, ancak ofis veya VPN network'ünüzdeki bir makineye erişemiyorsa Docker subnet'i büyük olasılıkla bu network ile çakışıyordur. Docker varsayılan olarak 172.17.0.0/16 aralığından itibaren adres tahsis eder. Pool'u /etc/docker/daemon.json içinde değiştirin:

{
  "default-address-pools": [
    { "base": "10.200.0.0/16", "size": 24 }
  ]
}

Ardından sudo systemctl restart docker komutunu çalıştırın ve etkilenen network'leri yeniden oluşturun. Mevcut bir network, oluşturulduğu subnet'i korur.

FAQ

Konteynerlerim neden birbirlerine hizmet adıyla erişemiyor?

Aynı ağda değiller. Compose, her hizmeti otomatik olarak <project>_default ağına ekler. Ancak bir hizmete networks: listesi eklediğiniz anda bu liste, hizmet için kullanılacak ağların tamamı olur ve varsayılan ağ artık örtük olarak eklenmez. docker network inspect <network> komutunu çalıştırın ve her iki konteynerin Containers bloğunda göründüğünü doğrulayın. Ayrıca hizmetlerden hiçbirinin network_mode: host kullanmadığını kontrol edin. Host modu kullanan bir konteyner hiçbir Docker ağında yer almaz ve hizmet adlarını çözümleyemez.

Bir hizmetin diğerine erişmesi için portları yayımlamam gerekir mi?

Hayır. Bir Compose ağında, o ağdaki diğer konteynerler her konteynerin tüm portlarına erişebilir. ports: yalnızca bir konteyneri Docker dışından gelen trafiğe açmak için kullanılır. expose: ise belgelendirme amacı taşır. Bir veritabanı portunu yayımlamak yaygın ve maliyetli bir uygulamadır. Çünkü veritabanını sunucunuzun genel arayüzüne açar.

Bridge ve host ağ iletişimi arasındaki fark nedir?

Bridge, konteynere kendi ağ ad alanını ve sanal anahtar üzerindeki adresini verir. Ayrıca konteynerler arasında otomatik ad çözümlemesi ve dışarı yönlendirilen trafiğin çevrilmesini sağlar. Host ise konteynerin doğrudan hostun ağ yığınını kullanmasını sağlar. Ayrı bir adres olmaz, hizmet adıyla çözümleme yapılamaz, port yayımlama gerekmez ve hostun diğer dinleyicilerinden yalıtım sağlanmaz. Bridge varsayılandır ve süreç hostun arayüzlerine ihtiyaç duymadığı sürece doğru tercihtir.

İki farklı Compose dosyasındaki konteynerleri nasıl bağlarım?

docker network create edge ile paylaşılan bir ağ oluşturun. Ardından bu ağı her iki dosyada external: true ile tanımlayın ve iletişim kurması gereken hizmetleri bu ağa bağlayın. Compose bu ağı oluşturmaz veya silmez. Oluşturma adımını atlarsanız Compose başlatmayı reddeder ve ağın harici olarak tanımlandığını, ancak bulunamadığını bildirir.

UFW portu engellediği hâlde konteynerime neden internetten erişilebiliyor?

Çünkü yayımlanan bir port, Docker'ın iptables'a eklediği yönlendirme kuralları tarafından işlenir. Bu kurallar UFW kurallarından önce eşleştirilir. Ayrıca yönlendirilen trafik, UFW'nin filtrelediği zincirden geçmez. Host tarafını "127.0.0.1:8080:80" ile loopback arayüzüne bağlayın ve internetten erişilebilir hizmetleri 80 ve 443 portlarında bir ters proxy'nin arkasına yerleştirin.