← Kursa Dön
📄 Text · 30 min

Custom Network'ler ve İleri Seviye Networking

Bu bölümün önceki derslerinde Docker networking'in temellerini, DNS mekanizmasını ve port mapping'i öğrendik. Şimdi son derste öğrendiklerimizi birleştirip production kalitesinde network mimarileri kuracağız. Custom network'lerin tüm özelliklerini, internal network'leri, farklı driver türlerini ve gerçek dünya senaryolarını inceleyeceğiz.

Bir üniversite kampüsünü düşün. Mühendislik fakültesinin kendi ağı var, tıp fakültesinin kendi ağı var. Mühendislik öğrencileri kendi aralarında dosya paylaşır ama tıp fakültesinin hasta kayıtlarına erişemez. Ortak kullanılan kütüphane ise herkesin erişebildiği ayrı bir ağda. Docker custom network'ler tam bu kampüs ağı mantığıyla çalışır.


Network Driver'ları — Farklı İhtiyaçlar, Farklı Çözümler

Docker'da birden fazla network driver'ı var ve her biri farklı bir senaryoya hizmet eder. Hepsini bilmene gerek yok ama en azından ne zaman hangisini kullanacağını bilmen lazım.

Bridge driver — en yaygın kullandığın ve bu kursta sürekli kullandığımız driver. Tek bir host üzerinde container'ları izole eder. Custom network oluşturduğunda varsayılan olarak bridge kullanılır:

docker network create mynet
# = docker network create --driver bridge mynet

Host driver — container'ın kendi network namespace'i olmaz, host'un ağını doğrudan kullanır. Daha önce bunu gördük, performans gerektiren durumlarda kullanılır.

Overlay driver — birden fazla Docker host'u birbirine bağlar. Docker Swarm veya Kubernetes gibi orchestration araçlarıyla kullanılır:

docker network create --driver overlay --attachable my-overlay-net

Macvlan driver — container'a gerçek bir MAC adresi verir, fiziksel ağda direkt görünür hale getirir:

docker network create -d macvlan \
    --subnet=192.168.1.0/24 \
    --gateway=192.168.1.1 \
    -o parent=eth0 \
    my-macvlan-net

None — ağ yok, tamamen izole. docker run --network none ile kullanılır.

Bu kursta %95 bridge driver kullanacaksın. Overlay, microservice orchestration'a geçtiğinde karşına çıkacak. Macvlan ise legacy sistemlerle entegrasyon gibi çok özel durumlarda gerekir.


Custom Network Oluşturma — Detaylı Seçenekler

Basit docker network create mynet demeyi zaten biliyorsun. Ama bazen daha fazla kontrol isteyeceksin. Mesela kendi subnet aralığını belirlemek, IP havuzunu sınırlamak veya network'e label eklemek.

Kendi subnet'ini belirterek bir network oluşturalım:

docker network create \
    --subnet=10.10.0.0/16 \
    --gateway=10.10.0.1 \
    mynet

Bu network'te container'lar 10.10.0.2'den başlayarak IP alacak. Gateway 10.10.0.1 olacak. Neden bunu yapmak istersin? Mesela şirketinin iç ağıyla çakışmayan bir IP aralığı seçmek istiyorsundur.

IP aralığını daha da daraltabilirsin:

docker network create \
    --subnet=10.10.0.0/16 \
    --ip-range=10.10.1.0/24 \
    --gateway=10.10.0.1 \
    mynet

Bu durumda Docker, container'lara sadece 10.10.1.1-10.10.1.254 aralığından IP verir. Geniş subnet'in geri kalanı başka amaçlar için ayrılmış kalır.

Label eklemek de çok faydalı — özellikle çok sayıda network'ün olduğu ortamlarda hangi network'ün hangi projeye ait olduğunu anlamak kolaylaşır:

docker network create \
    --label project=ecommerce \
    --label environment=production \
    mynet

Internal Network — İnternete Çıkış Yasak

Bu çok güçlü bir özellik. Internal network'teki container'lar birbirleriyle konuşabilir ama internete çıkamazlar. Veritabanı container'ın için düşün — PostgreSQL'in neden internete çıkması gereksin ki? Hiçbir sebebi yok. Hatta güvenlik açısından çıkmaması gerekir.

docker network create --internal secure-net

Hadi test edelim:

docker run -d --name secure-app --network secure-net alpine sleep 3600
docker run -d --name secure-db --network secure-net alpine sleep 3600

İç iletişimi deneyelim:

docker exec secure-app ping -c 2 secure-db
PING secure-db (172.21.0.3): 56 data bytes
64 bytes from 172.21.0.3: seq=0 ttl=64 time=0.1ms

Çalışıyor. Şimdi dış dünyaya erişimi deneyelim:

docker exec secure-app ping -c 2 google.com
ping: bad address 'google.com'

İnternet erişimi yok! Bu tam olarak istediğimiz şey. Veritabanı container'ın dış dünyayla iletişim kurmasına gerek yok — sadece API ile konuşsun yeter.

Peki API'nin hem veritabanına erişmesi hem de internete çıkması gerekiyorsa? Basit: API'yi iki network'e bağla:

docker network create --internal db-net
docker network create api-net

docker run -d --name db --network db-net postgres:16 -e POSTGRES_PASSWORD=secret
docker run -d --name api --network db-net node:20-alpine sleep 3600
docker network connect api-net api

Artık:

  • db → internet yok (db-net internal), sadece API ile konuşuyor

  • api → hem db'ye erişiyor (db-net üzerinden) hem internete çıkıyor (api-net üzerinden)

Bu, güvenlik katmanlarını çok zarif bir şekilde oluşturmamı sağlıyor.


Container'ları Çalışırken Bağlama ve Koparma

Custom network'lerin en güçlü özelliklerinden biri, çalışan container'ları network'lere bağlayıp koparabilmen. Varsayılan bridge'de bunu yapamazsın.

# Çalışan container'ı yeni network'e ekle
docker network connect mynet mycontainer

# IP adresi belirterek bağla
docker network connect --ip 10.10.1.100 mynet mycontainer

# Alias ile bağla
docker network connect --alias db-primary mynet mycontainer

# Network'ten kopar
docker network disconnect mynet mycontainer

Bir container birden fazla network'e bağlı olduğunda, her network'te farklı bir IP adresi alır:

docker run -d --name proxy --network frontend nginx
docker network connect backend proxy
docker network connect monitoring proxy

Şimdi proxy'nin network durumuna bakalım:

docker inspect proxy --format '{{range $key, $value := .NetworkSettings.Networks}}{{$key}}: {{$value.IPAddress}}{{"\n"}}{{end}}'
frontend: 172.18.0.2
backend: 172.19.0.5
monitoring: 172.20.0.3

Her network'te farklı IP'si var. Frontend'teki container'lar proxy'ye 172.18.0.2 ile erişirken, backend'tekiler 172.19.0.5 ile erişir. Ama hepsi proxy ismiyle de erişebilir — Docker DNS her network'te ayrı çalışır.


Statik IP Atama

Normalde Docker container'lara otomatik IP atar. Ama bazen sabit IP isteyebilirsin — mesela legacy bir uygulama belirli bir IP bekliyor:

docker network create \
    --subnet 10.10.0.0/24 \
    --gateway 10.10.0.1 \
    static-net

docker run -d --name web --network static-net --ip 10.10.0.100 nginx
docker run -d --name api --network static-net --ip 10.10.0.101 node:20-alpine sleep 3600
docker run -d --name db --network static-net --ip 10.10.0.200 -e POSTGRES_PASSWORD=secret postgres:16

Bu IP'ler restart'ta bile değişmez (aynı network'te kaldığı sürece).

⚠️ Ama şunu bil: Statik IP'yi yine de tercih etme. DNS ismi kullanmak her zaman daha iyi ve daha esnek. Statik IP sadece legacy sistemler veya çok özel durumlar için kullan.


Network İnceleme ve Debug

Bir network hakkında detaylı bilgi almak istediğinde inspect komutunu kullanırsın:

docker network inspect mynet

Bu sana network'ün driver'ını, subnet'ini, gateway'ini ve bağlı tüm container'ların listesini verir. Hangi container hangi IP'yi almış, hepsini görebilirsin.

Daha spesifik bilgiler için format parametresini kullanabilirsin:

# Subnet bilgisi
docker network inspect mynet --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'

# Bağlı container listesi
docker network inspect mynet --format '{{range .Containers}}{{.Name}} ({{.IPv4Address}}){{"\n"}}{{end}}'

Host'taki bridge interface'leri görmek için:

ip addr show type bridge

Ve ağ trafiğini analiz etmek için netshoot container'ını kullanabilirsin:

docker run --rm -it --network container:web nicolaka/netshoot tcpdump -i eth0 -c 20

Bu komut, web container'ının network namespace'ine bağlanıp trafiğini yakalar. Network sorunlarını debug etmek için çok güçlü bir araç.


Network Temizliği

Zamanla kullanılmayan network'ler birikir. Bunları temizlemek için:

docker network prune

Bu komut, hiçbir container'a bağlı olmayan tüm custom network'leri siler. Varsayılan bridge, host ve none'a dokunmaz.

Belirli bir network'ü silmek için:

docker network rm mynet

Eğer hâlâ container'lar bağlıysa hata alırsın. Önce container'ları kopar veya sil.


Production Network Mimarisi — Üç Katmanlı İzolasyon

Şimdi öğrendiğimiz her şeyi birleştirip production-grade bir network mimarisi kuralım. Bu, gerçek dünyada en yaygın kullanılan pattern'dır.

# Üç katman, üç network
docker network create frontend-net
docker network create backend-net
docker network create --internal data-net  # İnternet erişimi yok!

Neden üç katman? Çünkü:

  • Frontend: Dış dünyayla iletişim kurar (Nginx reverse proxy)

  • Backend: İş mantığını çalıştırır (API servisleri)

  • Data: Verileri saklar (veritabanları, cache) — internete çıkmasına gerek yok

Şimdi servisleri yerleştirelim:

# Katman 3 — Data (tamamen izole, internet yok)
docker run -d --name db --network data-net \
    -e POSTGRES_PASSWORD=secret \
    -v pgdata:/var/lib/postgresql/data \
    postgres:16

docker run -d --name redis --network data-net \
    redis:7 --maxmemory 256mb

# Katman 2 — Backend (köprü: data'ya ve frontend'e erişir)
docker run -d --name api --network backend-net \
    -e DATABASE_URL=postgres://postgres:secret@db:5432/postgres \
    -e REDIS_URL=redis://redis:6379 \
    node:20-alpine sleep 3600
docker network connect data-net api
docker network connect frontend-net api

# Katman 1 — Frontend (dışarıya açık)
docker run -d --name nginx --network frontend-net \
    -p 80:80 -p 443:443 \
    nginx:alpine

Erişim matrisine bakalım:

            nginx    api     db     redis   internet
nginx        -       ✅     ❌      ❌       ✅
api         ✅       -      ✅      ✅       ✅
db          ❌      ✅       -       ✅       ❌
redis       ❌      ✅      ✅        -       ❌

Bu mimari şunları garanti eder:

  • nginx doğrudan veritabanına erişemez — güvenlik

  • db ve redis internete çıkamaz — internal network

  • Tek dış erişim noktası nginx — kontrollü giriş

  • api her iki tarafa da erişir — köprü rolü

Bu, güvenlik denetimlerinden geçen, compliance gereksinimlerini karşılayan, production-ready bir mimari.


Microservice Mesh Pattern'ı

Daha büyük projelerde her servis grubunun kendi network'ü olur. Mesela bir e-ticaret uygulamasında:

docker network create auth-net
docker network create product-net
docker network create order-net
docker network create shared-net  # Ortak servisler (DB, Redis, RabbitMQ)

Her servisin veritabanı kendi izole network'ünde çalışır. Servisler arası iletişim ise shared-net veya servis-spesifik network'ler üzerinden yapılır:

# Auth servisi — kendi network'ü + shared'a erişim
docker run -d --name auth --network auth-net auth-service
docker network connect shared-net auth

# Product servisi — kendi network'ü + shared'a erişim + auth'a erişim
docker run -d --name product --network product-net product-service
docker network connect shared-net product
docker network connect auth-net product

# API Gateway — tüm servislere erişir
docker run -d --name gateway --network auth-net -p 80:80 api-gateway
docker network connect product-net gateway
docker network connect order-net gateway

Bu yaklaşım "en az yetki prensibi"ni (principle of least privilege) uygular: her servis sadece ihtiyaç duyduğu network'lere erişir, gerisi tamamen izole.


Macvlan — Fiziksel Ağa Doğrudan Bağlantı

Nadiren de olsa container'ın fiziksel ağda kendi MAC adresiyle görünmesini isteyebilirsin. Mesela legacy bir uygulama belirli bir IP'den gelecek trafiği bekliyor veya multicast gerekiyor.

docker network create -d macvlan \
    --subnet=192.168.1.0/24 \
    --gateway=192.168.1.1 \
    -o parent=eth0 \
    phys-net

docker run -d --name legacy-app \
    --network phys-net \
    --ip 192.168.1.150 \
    myapp

Bu container artık fiziksel ağda 192.168.1.150 IP'siyle doğrudan görünür. NAT yok, bridge yok — fiziksel ağdaki diğer makinelerden direkt erişilebilir.

⚠️ Bilinen kısıtlama: Host makinesi (192.168.1.100) macvlan container'ına (192.168.1.150) erişemez. Bu macvlan'ın doğasından kaynaklanan bir durum.

Macvlan'ı çok özel durumlar dışında kullanmayacaksın. Bridge driver çoğu senaryoyu çok iyi karşılıyor.


Gerçek Dünya Senaryosu: E-Ticaret Altyapısı Script'i

Öğrendiğimiz her şeyi birleştiren kapsamlı bir setup script'i yazalım:

#!/bin/bash
# setup-ecommerce.sh — Tam E-ticaret network altyapısı

echo "=== E-Ticaret Altyapısı Kuruluyor ==="

# Temizlik
docker network prune -f 2>/dev/null

# Network'ler
docker network create --subnet 10.1.0.0/24 --label project=ecommerce public-net
docker network create --subnet 10.2.0.0/24 --label project=ecommerce service-net
docker network create --subnet 10.3.0.0/24 --internal --label project=ecommerce data-net

echo "Network'ler oluşturuldu:"
docker network ls --filter label=project=ecommerce

# Data katmanı (internal — internet yok)
docker run -d --name postgres --network data-net \
    -e POSTGRES_PASSWORD=secret \
    -v pgdata:/var/lib/postgresql/data \
    postgres:16-alpine

docker run -d --name redis --network data-net \
    redis:7-alpine --maxmemory 256mb

# Servis katmanı
docker run -d --name auth-service --network service-net \
    --network-alias auth \
    node:20-alpine sleep 3600
docker network connect data-net auth-service

docker run -d --name product-service --network service-net \
    --network-alias products \
    node:20-alpine sleep 3600
docker network connect data-net product-service

# Public katmanı (reverse proxy)
docker run -d --name nginx --network public-net \
    -p 80:80 \
    nginx:alpine
docker network connect service-net nginx

echo ""
echo "=== Container'lar ==="
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

echo ""
echo "=== Network Topolojisi ==="
for net in public-net service-net data-net; do
    echo "$net:"
    docker network inspect $net --format '  {{range .Containers}}{{.Name}} ({{.IPv4Address}}){{"\n"}}{{end}}'
done

Bu script'i çalıştırdığında, tam izole bir e-ticaret altyapısı ayağa kalkacak. Her katman kendi network'ünde, veritabanları internete çıkamıyor, tek giriş noktası Nginx.


Network Sorun Giderme Rehberi

Networking'te sorun yaşadığında şu adımları sırayla takip et:

Adım 1 — Container hangi network'lerde?

docker inspect mycontainer --format '{{range $key, $val := .NetworkSettings.Networks}}{{$key}}: {{$val.IPAddress}}{{"\n"}}{{end}}'

Adım 2 — Network'te hangi container'lar var?

docker network inspect mynet --format '{{range .Containers}}{{.Name}} {{.IPv4Address}}{{"\n"}}{{end}}'

Adım 3 — DNS çalışıyor mu?

docker exec mycontainer nslookup target-container

Adım 4 — Port erişimi var mı?

docker exec mycontainer nc -zv target-container 5432

Adım 5 — Route tablosu normal mi?

docker exec mycontainer ip route

Bu beş adım, network sorunlarının %90'ını çözmene yardımcı olur.


Yaygın Hatalar

Hata 1 — Network silinemiyor: Hâlâ container'lar bağlı olduğunda network silinemez. Önce container'ları kopar veya sil.

Hata 2 — Subnet çakışması: İki network aynı subnet'i kullanamazsın. docker network create --subnet 172.18.0.0/16 net1 yaptıktan sonra aynı subnet'le ikinci bir network oluşturamazsın. Farklı subnet kullan.

Hata 3 — Internal network'te dış DNS çalışmıyor: Bu beklenen davranış. Internal network'te google.com çözümlenemez çünkü internet erişimi yok. Ama aynı network'teki container isimleri çalışır.


Bu Derste Ne Öğrendik?

Bu derste Docker networking'in ileri seviye özelliklerini öğrendik:

  • Custom network oluşturmanın farklı yolları: subnet, IP range, label, driver seçenekleri.

  • Internal network ile container'ların internet erişimini engelleyebilirsin — veritabanları için ideal.

  • Container'lar çalışırken network'e bağlanabilir ve koparılabilir.

  • Üç katmanlı izolasyon (public → service → data) production'ın altın standardı.

  • Macvlan ile container'lar fiziksel ağda doğrudan görünebilir — çok özel durumlar için.

  • Network'lere label ekle, anlamlı isim ver, kullanılmayanları prune ile temizle.

Bu, networking bölümünün son dersiydi. Artık container'ların nasıl iletişim kurduğunu, dış dünyaya nasıl açıldığını ve güvenli network mimarileri nasıl kurulacağını biliyorsun. Bir sonraki bölümde Docker'ın en kritik konularından birine geçeceğiz: veri kalıcılığı ve volumes.