Docker'da bir container'ın ağ davranışını, bağlandığı ağın sürücüsü (driver) belirler. Linux üzerinde Docker Engine ile gelen yerleşik sürücüler şunlardır: bridge (varsayılan, aynı sunucudaki container'lar için), host (container sunucunun ağını doğrudan kullanır), none (yalnızca loopback, tam yalıtım), overlay (Swarm ile birden fazla sunucuyu bağlar), macvlan ve ipvlan (container'ı fiziksel ağa doğrudan bağlar). Tek bir VPS üzerinde çalışan uygulamaların büyük çoğunluğu için doğru seçim, kendi oluşturduğunuz (user-defined) bir bridge ağıdır.

Bu yazıda her sürücünün ne yaptığını, hangi durumda tercih edildiğini, container'ın ağı nasıl gördüğünü, IP adresi ve DNS ayarlarının nasıl dağıtıldığını ve Compose dosyasında ağ modlarının nasıl seçildiğini resmî Docker belgelerine dayanarak anlatıyoruz. Sürücülerin ayrıntılı kullanımı serinin diğer yazılarında: bridge ağı, port yayınlama, macvlan ve ipvlan ve IPv6. Docker'a yeni başlıyorsanız önce Docker öğrenme rehberine bakabilirsiniz.

Container ağı nasıl görür?

Docker belgelerinin vurguladığı ilk nokta şudur: container, hangi tür ağa bağlı olduğunu ya da karşısındaki makinenin bir container olup olmadığını bilmez. Container'ın içinden bakıldığında yalnızca bir ağ arayüzü, bu arayüzün IP adresi, bir varsayılan ağ geçidi (gateway), bir yönlendirme tablosu ve DNS ayarları görünür. Bu yüzden uygulama kodunuzu değiştirmeden aynı imajı bridge ağında, host ağında ya da macvlan ağında çalıştırabilirsiniz; değişen şey, paketlerin sunucunun içinde hangi yoldan geçtiğidir.

Container'ların ağ erişimi varsayılan olarak açıktır ve dışarıya bağlantı kurabilirler. Linux üzerinde Docker Engine ilk kez başladığında "default bridge" adlı tek bir yerleşik ağ oluşturur. --network seçeneği vermeden başlattığınız her container bu ağa bağlanır. Bu ağdaki container'lar dış dünyaya "masquerading" ile çıkar: giden paketlerin kaynak adresi sunucunun adresiyle değiştirilir. Sunucunun internet erişimi varsa container için ek bir ayar gerekmez.

Yeni kurulmuş bir sunucuda docker network ls komutu üç ağı listeler. Belgelerdeki örnek çıktı şöyledir (kimlikler her kurulumda farklıdır):

bash
docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
17e324f45964        bridge              bridge              local
6ed54d316334        host                host                local
7092879f2cc8        none                null                local

Dikkat ederseniz none ağının sürücü sütununda null yazar. bridge, host ve none ağları Docker tarafından hazır gelir; bunları silmezsiniz, yalnızca kullanırsınız ya da kullanmazsınız.

Yerleşik sürücüler tek tek

Yerleşik sürücüler tek tek: bridge, host, none, overlay

bridge

Bir sürücü belirtmeden ağ oluşturursanız oluşan ağ bridge türündedir. Belgelere göre bridge ağları, aynı sunucuda çalışan ve birbiriyle konuşması gereken container'lar için kullanılır. Bir bridge ağının bir IPv4 alt ağı ve isteğe bağlı bir IPv6 alt ağı vardır. Aynı bridge ağındaki container'lar birbirine ve sunucuya sınırsız erişebilir, başka ağlardaki container'lar ve sunucunun dışından gelen bağlantılar ise engellenir. Dışarıdan erişim yalnızca -p ile yayınladığınız portlar üzerinden olur.

Varsayılan bridge ile sizin oluşturduğunuz bridge arasında önemli farklar vardır: kullanıcı tanımlı bridge ağlarında container'lar birbirini adıyla bulur, varsayılan ağda yalnızca IP adresiyle bulabilir. Docker belgeleri kullanıcı tanımlı bridge'i açıkça daha üstün sayar ve varsayılan bridge'i üretim için önermez. Ayrıntılar Docker bridge network yazısında.

host

host modunda container'ın ağ yığını sunucudan yalıtılmaz; container sunucunun ağ ad alanını (network namespace) paylaşır ve kendine ait bir IP adresi almaz. Container içinde 80 numaralı porta bağlanan bir uygulama, doğrudan sunucunun IP adresinin 80 numaralı portunda erişilebilir olur. Container'ın kendi IP adresi olmadığı için port eşleme bu modda işe yaramaz: -p, --publish, -P ve --publish-all seçenekleri yok sayılır ve Docker şu uyarıyı verir:

bash
WARNING: Published ports are discarded when using host network mode

Belgeler host modunun iki kullanım alanını sayar: performansı iyileştirmek ve çok geniş bir port aralığını yönetmesi gereken container'lar. Sebep, bu modda ağ adresi dönüştürmesi (NAT) yapılmaması ve her port için ayrı bir "userland-proxy" süreci oluşturulmamasıdır. Bedeli ise yalıtımın kaybıdır. Compose belgeleri bu modu kullanan bir container'ın sunucudaki bütün portlara erişebileceğini ve sunucudaki bütün ağ trafiğini gözlemleyebileceğini, bu nedenle yalnızca gerçekten gerektiğinde kullanılmasını söyler. Ağ dışındaki alanlarda (dosya sistemi, süreç ad alanı, kullanıcı ad alanı) container yalıtılmış olarak kalır.

Host sürücüsü Linux üzerindeki Docker Engine'de desteklenir; Docker Desktop'ta 4.34 ve sonraki sürümlerde ayarlardan açılan bir özellik olarak bulunur. Bir Swarm servisi de --network host ile çalıştırılabilir; bu durumda yönetim trafiği yine overlay ağından gider, ama servis container'ları veri için sunucunun portlarını kullanır. Bunun sonucu olarak 80 numaralı porta bağlanan bir servisten bir Swarm düğümünde yalnızca bir container çalışabilir.

none

--network none ile başlatılan container'ın ağ yığını tamamen yalıtılır; içeride yalnızca loopback aygıtı oluşturulur. Belgelerdeki örnekte ip link show çıktısında sadece lo arayüzü görünür:

bash
docker run --rm --network none alpine:latest ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

Belgelere göre none sürücüsünü kullanan container'larda IPv6 loopback adresi de yapılandırılmaz; yalnızca 127.0.0.1/8 bulunur. Ayrıca none Swarm servisleri için kullanılamaz. Ağa hiç ihtiyaç duymayan bir işi çalıştırırken bu mod, yanlışlıkla dışarıya bağlantı kurulmasının önüne geçer.

overlay

Overlay ağları birden fazla Docker daemon'ını birbirine bağlar ve Swarm servislerinin ve container'larının farklı düğümler arasında konuşmasını sağlar. Belgelere göre bu yaklaşım işletim sistemi düzeyinde yönlendirme kurma ihtiyacını ortadan kaldırır. Farklı sunuculardaki container'ların haberleşmesi gerekiyorsa ya da birlikte çalışan servisleri Swarm ile yönetiyorsanız overlay en uygun sürücüdür. Swarm kurulumu ve servis ağları Docker Swarm kurulumu yazısında anlatılıyor.

macvlan ve ipvlan

Macvlan, her container'a kendi MAC adresini verir ve container ağdaki diğer cihazlara fiziksel bir makine gibi görünür. Belgeler bu sürücüyü özellikle sanal makine düzeninden geçiş yapanlar ve doğrudan fiziksel ağa bağlı olmayı bekleyen eski uygulamalar için önerir. IPvlan benzer şekilde çalışır ama container'lara ayrı MAC adresi atamaz; bir ağ arayüzüne ya da porta atanabilecek MAC adresi sayısında sınır varsa tercih edilir. İkisi de bulut sağlayıcılarında çoğu zaman kullanılamaz; ayrıntılar Docker macvlan ve ipvlan yazısında.

Ağ eklentileri

Docker'ın ağ alt sistemi eklenebilir (pluggable) yapıdadır. Yerleşik sürücülerin yanında üçüncü taraf ağ eklentileri kurup kullanabilirsiniz. Belgeler bunları özel ağ yığınlarıyla bütünleşmek için bir seçenek olarak anar.

Sürücü karşılaştırması

SürücüContainer IP adresiPort yayınlamaTipik kullanım
bridge (kullanıcı tanımlı)Ağın alt ağındanGerekir (-p)Tek sunucudaki çok servisli uygulamalar
bridge (varsayılan)docker0 alt ağındanGerekir (-p)Özel ihtiyacı olmayan tekil container'lar
hostYok, sunucunun ağı kullanılırYok sayılırPerformans, çok geniş port aralığı
noneYok, yalnızca loopbackYokAğ gerektirmeyen işler
overlayOverlay alt ağındanSwarm yönlendirmesiBirden fazla sunucu, Swarm servisleri
macvlanFiziksel ağın alt ağındanGerekmezFiziksel cihaz gibi görünmesi gereken uygulamalar
ipvlanFiziksel ağın alt ağındanGerekmezMAC adresi sınırı olan ağlar, L3 yönlendirme

Tablodaki "Gerekmez" ifadesi, container zaten fiziksel ağdan erişilebilir bir adres aldığı için port eşlemeye gerek kalmaması anlamındadır. Güvenlik açısından önemli bir ayrıntı daha var: Docker belgelerine göre Docker güvenlik duvarı kurallarını bridge ağları için oluşturur; ipvlan, macvlan ve host ağları için hiçbir kural oluşturmaz. Bu ağlarda erişim denetimi tamamen sizin sunucu ve ağ yapılandırmanıza kalır. Bridge tarafındaki kurallar Docker iptables ve UFW yazısında ele alınıyor.

Container ağı paylaşma: container:&lt;ad&gt; modu

Container ağı paylaşma: container:<ad> modu

Kullanıcı tanımlı ağlara ek olarak bir container'ı başka bir container'ın ağ yığınına doğrudan bağlayabilirsiniz. Bunun için --network container:<ad|id> biçimi kullanılır. İki container aynı ağ arayüzünü, aynı IP adresini ve aynı loopback'i paylaşır. Belgelerdeki örnekte Redis yalnızca 127.0.0.1 adresini dinler; ikinci container aynı ağ yığınına katıldığı için redis-cli ile 127.0.0.1 üzerinden bağlanabilir:

bash
docker run -d --name redis redis --bind 127.0.0.1
docker run --rm -it --network container:redis redis redis-cli -h 127.0.0.1

Bu modda ağ ayarlarının sahibi ilk container olduğu için şu seçenekler desteklenmez: --add-host, --hostname, --dns, --dns-search, --dns-option, --mac-address, --publish, --publish-all ve --expose. Port yayınlamak istiyorsanız bunu ağ yığınının sahibi olan container üzerinde yapmanız gerekir. Compose dosyalarında aynı davranış network_mode: "service:[servis adı]" ile elde edilir.

Birden fazla ağa bağlanma ve varsayılan ağ geçidi

Belgeler ağa bağlanmayı bir makineye Ethernet kablosu takmaya benzetir. Bir makine birden fazla ağa bağlanabildiği gibi bir container da birden fazla Docker ağına bağlanabilir. Örneğin bir ön yüz container'ı dış erişimi olan bir bridge ağına ve arka uç servisleriyle konuşmak için --internal ile oluşturulmuş, dış erişimi olmayan bir ağa aynı anda bağlı olabilir. Farklı türdeki ağlar da birleştirilebilir: internet erişimi için bir ipvlan ağı, yerel servisler için bir bridge ağı gibi.

Paket gönderilirken hedef doğrudan bağlı ağlardan birindeyse paket o ağa gider; değilse varsayılan ağ geçidine gönderilir. Varsayılan ağ geçidini Docker seçer ve container'ın ağ bağlantıları değiştikçe bu seçim değişebilir. Belirli bir ağın her zaman varsayılan ağ geçidi olmasını istiyorsanız gw-priority değerini kullanırsınız. Varsayılan değer 0'dır ve en yüksek önceliğe sahip ağın ağ geçidi seçilir; dolayısıyla bir ağa 1 vermek yeterlidir:

bash
docker run --network name=gwnet,gw-priority=1 --network anet1 --name myctr myimage
docker network connect anet2 myctr

Çalışan bir container'ı ek bir ağa docker network connect ile bağlarsınız. Bağlanırken --ip ve --ip6 ile o ağdaki adresi, --alias ile o ağda geçerli ek bir ad verebilirsiniz.

IP adresi dağıtımı ve alt ağ havuzları

Bir ağ oluşturduğunuzda IPv4 adres dağıtımı varsayılan olarak açıktır ve --ipv4=false ile kapatılabilir; IPv6 ise --ipv6 ile açılır. Container bağlandığı her Docker ağı için o ağın alt ağından bir IP adresi alır. Alt ağı açıkça verebilirsiniz (--subnet 192.0.2.0/24); vermezseniz Docker, daemon'ın "default address pools" adlı havuzlarından otomatik bir alt ağ seçer. Belgelere göre yerleşik varsayılan havuz şu yapılandırmaya eşdeğerdir:

json
{
  "default-address-pools": [
    { "base": "172.17.0.0/16", "size": 16 },
    { "base": "172.18.0.0/16", "size": 16 },
    { "base": "172.19.0.0/16", "size": 16 },
    { "base": "172.20.0.0/14", "size": 16 },
    { "base": "172.24.0.0/14", "size": 16 },
    { "base": "172.28.0.0/14", "size": 16 },
    { "base": "192.168.0.0/16", "size": 20 }
  ]
}

Burada base dağıtımın yapılacağı alt ağı, size her ağa verilecek önek uzunluğunu belirtir. Docker sunucuda kullanılan adres öneklerinden kaçınmaya çalışır, ama bazı ortamlarda (örneğin sunucunun bağlı olduğu özel ağ 172.16.0.0/12 aralığındaysa) yönlendirme çakışmalarını önlemek için bu havuzu özelleştirmeniz gerekebilir. Varsayılan havuzlar büyük alt ağlar kullandığı için oluşturabileceğiniz ağ sayısı sınırlıdır. Belgelerdeki örnekte tek bir 172.17.0.0/16 tabanı /24 parçalara bölünerek 256 ağ elde edilir:

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

Docker Engine 29.0.0 ile gelen bir yenilik de var: --subnet seçeneğinde belirtilmemiş adres kullanarak varsayılan havuzdan belirli uzunlukta bir alt ağ isteyebilirsiniz, örneğin --subnet 0.0.0.0/24 ya da --subnet ::/56. Belgeler bir uyarı ekler: Docker bu desteğin olmadığı eski bir sürüme düşürülürse bu şekilde oluşturulmuş ağlar kullanılamaz hale gelir; silinip yeniden oluşturulmaları ya da daemon'ın 29.0.0 veya sonrasına döndürülmesi gerekir. daemon.json dosyasının genel kullanımı için daemon.json yapılandırma yazısına bakın.

DNS ve ad çözümleme

DNS ve ad çözümleme: --dns, --dns-search, --dns-option, --hostname

Container'lar varsayılan olarak sunucunun DNS sunucularını kullanır ve ayarlarını sunucudaki /etc/resolv.conf dosyasından devralır. Burada sürücüye göre önemli bir fark vardır. Varsayılan bridge ağına bağlanan container'lar bu dosyanın bir kopyasını alır. Kullanıcı tanımlı bir ağa bağlanan container'lar ise Docker'ın gömülü DNS sunucusunu kullanır. Gömülü DNS sunucusunun adresi 127.0.0.11'dir; dış adlar için gelen sorguları sunucuda yapılandırılmış DNS sunucularına iletir. Belgelere göre bunun IPv6 karşılığı yoktur, ama IPv4 adresi yalnızca IPv6 kullanan container'larda bile çalışır. Uygulamanız açık bir DNS sunucusu adresi istiyorsa 127.0.0.11 verebilirsiniz.

Birden fazla DNS sunucusu tanımladığınızda davranış da farklıdır. Varsayılan bridge ağında sorguların nasıl yapılacağına container içindeki çözümleyici kütüphane karar verir: bazıları sunucuları sırayla dener, bazıları paralel sorgulayıp ilk gelen yanıtı (NXDOMAIN olsa bile) kullanır. Kullanıcı tanımlı ağda gömülü DNS sunucusu üst sunucuları sırayla sorgular ve başarılı bir yanıt ya da NXDOMAIN aldığında durur.

BayrakNe yapar
--dnsDNS sunucusunun IP adresi; birden fazla sunucu için bayrağı tekrarlayın. Adres container'ın ağ ad alanından kullanılır.
--dns-searchTam nitelikli olmayan adlar için arama alan adı; birden fazlası için bayrağı tekrarlayın.
--dns-optionresolv.conf seçeneği olarak anahtar-değer çifti.
--hostnameContainer'ın kendisi için kullandığı ad; verilmezse container kimliğidir.

--dns=127.0.0.1 yazarsanız bu adres sunucunun değil container'ın kendi loopback adresi anlamına gelir; çünkü DNS istekleri container'ın ağ ad alanından gönderilir. Sunucunun /etc/hosts dosyasındaki özel kayıtlar da container'lara geçmez; ek kayıt gerekiyorsa --add-host ya da Compose'daki extra_hosts kullanılır.

Compose'ta ağ modu seçimi

Compose varsayılan olarak her proje için <proje-adı>_default adlı bir bridge ağı oluşturur ve bütün servisleri bu ağa bağlar. Belgeler bu varsayılanı en güvenli mod olarak tanımlar. Servis düzeyinde network_mode ile host, none, service:{ad} ya da container:{ad} seçebilir, üst düzey networks anahtarıyla kendi ağlarınızı tanımlayabilirsiniz. Aşağıdaki dosya beş servisi farklı ağ düzenlerine yerleştirir ve Docker CLI 29.8.1, Docker Compose v5.5.1 ile docker compose config --quiet komutundan hatasız geçmiştir:

yaml
services:
  web:
    image: nginx:latest
    networks:
      - frontend
    ports:
      - "127.0.0.1:8080:80"
  api:
    image: example/api:latest
    networks:
      - frontend
      - backend
  db:
    image: postgres:18
    networks:
      - backend
  monitor:
    image: netdata/netdata
    network_mode: host
  batch:
    image: alpine:latest
    command: ["sh", "-c", "echo ağ yok"]
    network_mode: none

networks:
  frontend:
  backend:
    internal: true

Bu düzende web yalnızca frontend ağındadır ve portu sadece sunucunun loopback adresine yayınlanır. api iki ağa birden bağlı olduğu için hem web hem db ile konuşabilir. db ise internal: true olan backend ağındadır; Compose belgelerine göre bu ağın dış bağlantı için varsayılan ağ geçidi yoktur. monitor sunucunun ağını kullanır ve servis adıyla DNS çözümlemesi bu container için çalışmaz. batch ise hiçbir ağa çıkamaz.

network_mode ile networks aynı serviste birlikte kullanılamaz. Bunu denediğinizde Compose dosyayı reddeder. Aşağıdaki çıktı, network_mode: host ve networks içeren bir dosyada docker compose config --quiet komutunun gerçek çıktısıdır:

bash
docker compose -f compose.yaml config --quiet
service monitor declares mutually exclusive `network_mode` and `networks`: invalid compose project

Compose'taki temel ağ kullanımı (servis adıyla bağlanma, override dosyaları) Docker Compose rehberinde anlatılıyor; bu yazı yalnızca ağ türü seçimine odaklanıyor.

Hangi sürücüyü ne zaman seçmeli?

  • Tek bir VPS üzerinde web, API ve veritabanından oluşan bir uygulama çalıştırıyorsanız kullanıcı tanımlı bir bridge ağı (Compose'un varsayılan ağı da budur) kullanın.
  • Veritabanı gibi dışarıya hiç çıkmaması gereken servisleri ayrı bir internal ağa koyun ve yalnızca onlarla konuşması gereken servisleri o ağa da bağlayın.
  • Container çok geniş bir port aralığı kullanıyorsa ya da NAT'ın getirdiği ek işlemden kaçınmak istiyorsanız host modunu düşünün, ama yalıtımın kalktığını unutmayın.
  • Birden fazla sunucuya yayılan servisler için Swarm ve overlay ağı kullanın.
  • Container'ın yerel ağda kendi MAC ve IP adresiyle görünmesi gerekiyorsa ve ağ donanımınız buna izin veriyorsa macvlan; MAC adresi sınırı varsa ipvlan seçin.
  • Ağ gerektirmeyen tek seferlik işlerde none kullanın.

Sık yapılan hatalar

  • Varsayılan bridge'de container adıyla bağlanmaya çalışmak: varsayılan ağda ad çözümleme yoktur; ping: bad address türünde hata alırsınız. Kullanıcı tanımlı bir ağ oluşturun.
  • Host modunda -p kullanmak: port eşleme bu modda yok sayılır. Compose belgeleri network_mode: host ile ports birlikte kullanıldığında çalışma zamanında hata oluşacağını belirtir; docker compose config bu birleşimi reddetmez, hata container başlatılırken ortaya çıkar.
  • IP adresine güvenmek: Compose belgelerine göre container IP adresleri her başlatmada dinamik olarak verilir ve yeniden oluşturmada değişir. Servislere adıyla erişin.
  • Alt ağ çakışmasını gözden kaçırmak: sunucunun özel ağı Docker'ın varsayılan havuzlarıyla çakışıyorsa default-address-pools ayarını değiştirin.
  • macvlan, ipvlan ve host ağlarında Docker'ın güvenlik duvarı kuralı koyacağını sanmak: belgelere göre bu ağlar için kural oluşturulmaz.

Sık Sorulan Sorular

Docker'da varsayılan network hangisidir?

Linux üzerinde Docker Engine ilk başladığında "bridge" adlı varsayılan bridge ağını oluşturur ve --network verilmeyen container'lar bu ağa bağlanır. Compose ise her proje için ayrı bir <proje-adı>_default bridge ağı oluşturur.

host network daha mı hızlı?

Belgeler host modunu performans iyileştirmesi için kullanılabilecek bir seçenek olarak anar, çünkü NAT yapılmaz ve port başına userland-proxy oluşturulmaz. Bir hız rakamı vermez. Karşılığında container'ın ağ yalıtımı ortadan kalkar.

Bir container aynı anda birden fazla ağa bağlanabilir mi?

Evet. --network bayrağını birden fazla kez verebilir ya da çalışan container'ı docker network connect ile yeni bir ağa bağlayabilirsiniz. Hangi ağın varsayılan ağ geçidi olacağını gw-priority ile belirlersiniz.

Container'ın içinden 127.0.0.11 adresi ne işe yarar?

Kullanıcı tanımlı ağlardaki container'ların kullandığı gömülü DNS sunucusunun adresidir. Container adlarını çözer ve dış adlar için sorguları sunucunun DNS sunucularına iletir.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: Docker öğrenme rehberi · Docker bridge network · Docker port yayınlama · Docker iptables ve UFW · Docker macvlan ve ipvlan · Docker IPv6 · Docker Compose rehberi