Docker'da IPv6 ağ başına açılır: kullanıcı tanımlı bir ağı docker network create --ipv6 ile ya da Compose'ta enable_ipv6: true ile oluşturursunuz, varsayılan bridge için ise daemon.json içinde "ipv6": true ve "fixed-cidr-v6" tanımlayıp daemon'ı yeniden başlatırsınız. Alt ağ vermezseniz Docker otomatik olarak bir Unique Local Address (ULA) /64 alt ağı seçer. Belgelere göre IPv6 yalnızca Linux sunucularda çalışan Docker daemon'larında desteklenir.

Bu yazıda IPv6 ağı oluşturmayı, varsayılan bridge'de IPv6'yı açmayı, dinamik IPv6 alt ağ havuzlarını, yalnızca IPv6 kullanan ağları, IPv6'da port yayınlamanın ve doğrudan yönlendirmenin (routed modu) nasıl çalıştığını ve Docker in Docker ortamındaki özel durumu ele alıyoruz. Bridge ağlarının genel işleyişi Docker bridge network, port eşlemenin ayrıntıları Docker port yayınlama yazısında. Serinin tamamı için Docker öğrenme rehberine bakın.

IPv6 ağı oluşturmak

Belgeler üç yol gösterir. En kısası, Docker'ın alt ağı kendisinin seçmesine izin vermektir:

bash
docker network create --ipv6 ip6net

Belirli bir IPv6 alt ağı kullanmak için --subnet eklenir:

bash
docker network create --ipv6 --subnet 2001:db8::/64 ip6net

Compose dosyasında ise ağ tanımına enable_ipv6: true ve bir ipam alt ağı yazılır. Belgelerdeki örnek şöyledir:

yaml
networks:
  ip6net:
    enable_ipv6: true
    ipam:
      config:
        - subnet: 2001:db8::/64

Ağ oluşturulduktan sonra ona bağlanan container'lar IPv6 adresi alır. Belgelerdeki örnekte -p 80:80 ile yayınlanan port hem IPv6 hem IPv4 üzerinde açılır ve sunucunun IPv6 loopback adresine yapılan istek yanıt verir. traefik/whoami imajının döndürdüğü çıktı (belgedeki örnek), container'ın hem IPv4 hem IPv6 adreslerini listeler:

bash
docker run --rm --network ip6net -p 80:80 traefik/whoami

curl http://[::1]:80
Hostname: ea1cfde18196
IP: 127.0.0.1
IP: ::1
IP: 172.17.0.2
IP: 2001:db8::2
IP: fe80::42:acff:fe11:2
RemoteAddr: [2001:db8::1]:37574
GET / HTTP/1.1
Host: [::1]
User-Agent: curl/8.1.2
Accept: */*

Çıktıda dikkat edilmesi gereken nokta, bir IPv6 ağının IPv4'ü kapatmamasıdır: container hâlâ bir IPv4 adresi de alır. Ağ oluştururken IPv4 adres dağıtımı varsayılan olarak açıktır; yalnızca IPv6 istiyorsanız bunu ayrıca kapatmanız gerekir.

Yalnızca IPv6 kullanan ağlar

Bridge ağında ve container'larında IPv4 adres yapılandırmasını atlamak için ağı --ipv4=false ile oluşturup IPv6'yı --ipv6 ile açarsınız:

bash
docker network create --ipv6 --ipv4=false v6net

Compose karşılığı enable_ipv4: false ve enable_ipv6: true anahtarlarıdır. Belgelere göre IPv4 adres yapılandırması varsayılan bridge ağında kapatılamaz; yalnızca IPv6 kullanan bir düzen her zaman kullanıcı tanımlı bir ağ gerektirir. Bu ağlarda ad çözümleme de çalışmaya devam eder: Docker'ın gömülü DNS sunucusunun adresi 127.0.0.11'dir, bunun IPv6 karşılığı yoktur, ama belgeler IPv4 adresinin yalnızca IPv6 kullanan container'larda bile çalıştığını belirtir. Uygulamanız açık bir DNS sunucusu adresi isterse 127.0.0.11 verebilirsiniz.

Varsayılan bridge ağında IPv6

Varsayılan bridge ağında IPv6: ipv6, bip6, fixed-cidr-v6, default-gateway-v6

Varsayılan bridge ağı için IPv6, /etc/docker/daemon.json dosyasında açılır. Belgelerdeki en kısa yapılandırma şudur:

json
{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8:1::/64"
}

ipv6 varsayılan ağda IPv6'yı açar, fixed-cidr-v6 varsayılan bridge ağına bir alt ağ atayarak dinamik IPv6 adres dağıtımını etkinleştirir. Belgeler ayrıca ip6tables seçeneğini anar: ağ yalıtımı ve port eşleme sağlayan ek IPv6 paket filtresi kurallarını açar, varsayılan olarak etkindir ama kapatılabilir. Dosyayı kaydettikten sonra daemon'ı yeniden başlatırsınız:

bash
sudo systemctl restart docker

Bridge sürücüsü belgesi varsayılan bridge için iki ek seçenek daha tanımlar. Bu dört seçenek yalnızca varsayılan bridge'i etkiler, kullanıcı tanımlı ağlarda kullanılmaz:

SeçenekZorunlu mu?Anlamı
ipv6EvetVarsayılan bridge için IPv6'yı açar
bip6HayırVarsayılan köprünün adresi; container'lar bunu varsayılan ağ geçidi olarak kullanır ve ağın alt ağını da belirler
fixed-cidr-v6HayırDocker'ın container'lara otomatik dağıtabileceği adres aralığı; önek normalde /64 ya da daha kısa olmalıdır
default-gateway-v6HayırVerilmezse fixed-cidr-v6 alt ağının ilk adresi kullanılır
json
{
  "ipv6": true,
  "bip6": "2001:db8::1111/64",
  "fixed-cidr-v6": "2001:db8::/64",
  "default-gateway-v6": "2001:db8:abcd::89"
}

bip6 verilmezse fixed-cidr-v6 bridge ağının alt ağını belirler; ikisi de verilmezse bir ULA öneki seçilir. Belgeler yerel bir ağda deneme yaparken bağlantı yerel (link local, fe80::/10) bir önek yerine ULA önekinin (fd00::/8) kullanılmasını önerir. Bununla birlikte bridge belgesinin genel tavsiyesi değişmez: varsayılan bridge üretimde önerilmez; IPv6'yı kullanıcı tanımlı ağlarda açmak hem daha esnek hem daha yalıtılmıştır. daemon.json düzenlemenin genel kuralları için daemon.json yapılandırma yazısına bakın.

Dinamik IPv6 alt ağ dağıtımı

--subnet ile alt ağ vermediğiniz kullanıcı tanımlı ağlar, yedek olarak daemon'ın varsayılan adres havuzlarını kullanır. Bu, Compose dosyasında enable_ipv6: true ile oluşturulan ağlar için de geçerlidir. Yerleşik varsayılan havuz yapılandırması hiçbir IPv6 havuzu içermez. Belgelere göre default-address-pools içinde IPv6 havuzu yoksa ve alt ağ verilmemişse IPv6 açıldığında ULA adresleri kullanılır. Bu /64 alt ağları, Docker Engine'in rastgele üretilmiş kimliğine dayanan 40 bitlik bir Global ID içerir ve böylece yüksek olasılıkla benzersiz olur.

Dinamik dağıtım için kendi IPv6 havuzlarınızı kullanmak istiyorsanız daemon'ın adres havuzlarını elle yapılandırmanız gerekir ve belgelere göre bu yapılandırma hem varsayılan IPv4 havuzlarını hem de bir ya da daha fazla kendi IPv6 havuzunuzu içermelidir. Yalnızca IPv6 havuzu yazarsanız IPv4 havuzlarını tanımlamamış olursunuz. Belgelerdeki örnekte iki havuz da 256 alt ağ sağlar: /16 havuzdan /24 IPv4 alt ağları, /56 havuzdan /64 IPv6 alt ağları:

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

Docker Engine 29.0.0 ile belirtilmemiş adres kullanarak varsayılan havuzlardan belirli uzunlukta alt ağ istemek de mümkün oldu. Belgelerdeki örnek bir /56 IPv6 ve bir /24 IPv4 alt ağı ister; docker network inspect çıktısı Docker'ın seçtiği alt ağları gösterir (belgedeki örnek çıktı):

bash
docker network create --ipv6 --subnet ::/56 --subnet 0.0.0.0/24 mynet
6686a6746b17228f5052528113ddad0e6d68e2e3905d648e336b33409f2d3b64
docker network inspect mynet -f '{{json .IPAM.Config}}' | jq .
[
  {
    "Subnet": "172.19.0.0/24",
    "Gateway": "172.19.0.1"
  },
  {
    "Subnet": "fdd3:6f80:972c::/56",
    "Gateway": "fdd3:6f80:972c::1"
  }
]

Belgeler bu özellikle ilgili bir uyarı ekler: Docker bu desteğin olmadığı eski bir sürüme düşürülürse bu yolla oluşturulan 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.

IPv6 ve port yayınlama

IPv6 ve port yayınlama: Sunucu adresi verilmemişse, bridge ağı yalnızca IPv4 ise ve..., Varsayılan bağlama adresini (host_binding_ipv4) :, Bir yayını yalnızca IPv4 ile sınırlamak...

Port yayınlama IPv6'da da IPv4'teki gibi çalışır: sunucu adresi verilmezse port bütün sunucu adreslerinde, 0.0.0.0 ve [::] üzerinde açılır. Yalnızca sunucuya açmak için IPv6 loopback'i köşeli parantezle ve tırnakla yazarsınız: -p '[::1]:8080:80'. Belgelerdeki üç ayrıntı IPv6 açısından özellikle önemlidir:

  • Sunucu adresi verilmemişse, bridge ağı yalnızca IPv4 ise ve --userland-proxy=true (varsayılan) ise, sunucunun IPv6 adreslerindeki portlar container'ın IPv4 adresine eşlenir. Yani IPv6 ağı açmasanız bile sunucunun IPv6 adresinden gelen istemciler yayınlanan porta ulaşabilir.
  • Varsayılan bağlama adresini (host_binding_ipv4) :: yapmak, adres belirtilmemiş eşlemelerin yalnızca sunucunun IPv6 adreslerinde açılması demektir; 0.0.0.0 ise IPv4 ve IPv6 adreslerinin tamamını kapsar.
  • Bir yayını yalnızca IPv4 ile sınırlamak için adresi eşlemeye yazmalısınız, örneğin -p 0.0.0.0:8080:80.

Compose'ta IPv6 adresleri köşeli parantez içinde yazılabilir; başvuru belgesi "[::1]:6001:6001" ve "::1:6000:6000" biçimlerini örnek verir. Engine 29.9.0 sürüm notlarına göre userland proxy açıkken yayınlanmış Swarm servis portlarına sunucunun IPv6 adreslerinden erişmek artık test edilen ve desteklenen bir özelliktir.

NAT yerine doğrudan yönlendirme: routed modu

Belgeler, özellikle IPv6'da NAT kullanmak yerine dış yönlendirmeyi container adreslerine doğrudan ulaşacak şekilde kurmayı tercih edebileceğinizi belirtir ("direct routing"). Bunun için bridge sürücüsünün com.docker.network.bridge.gateway_mode_ipv6 seçeneğini routed yaparsınız. Bu modda NAT ve masquerading kuralları kurulmaz, ama yalnızca yayınlanan container portlarının erişilebilir olması için güvenlik duvarı kuralları yine kurulur. Container'dan çıkan paketler sunucunun değil container'ın adresini kullanır. Belgelerdeki örnek IPv6 için routed, IPv4 için varsayılan nat modunu kullanır:

bash
docker network create --ipv6 --subnet 2001:db8::/64 -o com.docker.network.bridge.gateway_mode_ipv6=routed mynet
docker run --network=mynet -p 8080:80 myimage

Sonuç şudur: IPv6 tarafında 80 portu container'ın IPv6 adresinde açılır, sunucunun IP adreslerinde 8080 açılmaz ve giden paketler container adresini kullanır. IPv4 tarafında ise container'ın 80 portu sunucunun 8080 portundan erişilebilir, dışarıdan doğrudan erişilemez ve giden bağlantılar sunucunun adresiyle masquerade edilir. Eşlemeyi yalnızca IPv6'ya uygulamak için belgeler belirtilmemiş IPv6 adresini kullanıp sunucu portu yazmamayı önerir: -p '[::]::80'.

Routed moddaki bir porta uzak makinelerin erişebilmesi için Docker sunucusundaki bir dış adres üzerinden container ağına giden bir yolları olmalıdır. Aynı L2 ağındaki makineler bunu ek ağ yapılandırması olmadan kurabilir; yerel ağın dışındaki makineler ise ancak ağdaki yönlendiriciler buna izin verecek şekilde yapılandırılmışsa doğrudan yönlendirme kullanabilir. Bir VPS'te bu, sağlayıcınızın ağındaki yönlendiricilerin container alt ağına giden yolu bilmesine bağlıdır. Ağ geçidi modlarının tamamı port yayınlama, güvenlik duvarı tarafı Docker iptables ve UFW yazısında.

Compose ile IPv6 örneği

Aşağıdaki dosya iki ağ tanımlar: ip6net çift yığınlıdır ve sabit bir ULA alt ağı kullanır; v6net yalnızca IPv6 kullanır ve IPv6 için routed ağ geçidi modunu seçer, alt ağını ise Docker'ın dinamik dağıtımına bırakır. Dosya Docker CLI 29.8.1, Docker Compose v5.5.1 ile docker compose config --quiet doğrulamasından geçmiştir:

yaml
services:
  web:
    image: traefik/whoami
    ports:
      - "80:80"
    networks:
      - ip6net
  v6only:
    image: alpine:latest
    command: ["sleep", "infinity"]
    networks:
      - v6net

networks:
  ip6net:
    enable_ipv6: true
    ipam:
      config:
        - subnet: fd12:3456:789a::/64
  v6net:
    enable_ipv4: false
    enable_ipv6: true
    driver_opts:
      com.docker.network.bridge.gateway_mode_ipv6: routed

web servisinin "80:80" eşlemesi sunucu adresi içermediği için hem IPv4 hem IPv6 adreslerinde açılır. Compose başvurusu sabit IPv6 adresi vermek için servis tarafında ipv6_address anahtarını ve bu adresi kapsayan bir ipam alt ağını şart koşar. docker compose config sözdizimini denetler; sunucunuzun IPv6 bağlantısı olup olmadığını ya da alt ağın yönlendirilip yönlendirilmediğini bilemez. Bunlar Docker Engine üzerinde ağ oluşturulurken ve trafik aktığında ortaya çıkar.

Docker in Docker ve ip6_tables

Belgelere göre nftables yerine xtables (eski iptables) kullanan bir sunucuda, bir IPv6 Docker ağı oluşturulmadan önce ip6_tables çekirdek modülünün yüklenmiş olması gerekir; modül normalde Docker başlarken otomatik yüklenir. Güncel bir resmî docker imajına dayanmayan bir Docker in Docker ortamı çalıştırıyorsanız sunucuda modprobe ip6_tables çalıştırmanız gerekebilir. Alternatif olarak container içindeki Docker Engine için --ip6tables=false daemon seçeneğiyle ip6tables kullanımı kapatılabilir.

bash
modprobe ip6_tables

macvlan ve ipvlan ağlarında IPv6

Fiziksel ağa doğrudan bağlanan sürücülerde IPv6 iki şekilde kullanılabilir. Birincisi Docker'ın IPAM'ının yönettiği bir IPv6 alt ağı vermektir. İkincisi container'ların adreslerini üst ağdaki bir yönlendiriciden SLAAC ile almasıdır; bunun için ağda IPv6 alt ağı yoksa Docker arayüzde IPv6'yı kapattığından, container'ı bağlarken com.docker.network.endpoint.sysctls=net.ipv6.conf.IFNAME.disable_ipv6=0 sürücü seçeneği verilir. Ayrıntılar ve örnekler Docker macvlan ve ipvlan yazısında.

Engine 29 ile gelen IPv6 ile ilgili değişiklikler

Sürüm notlarında IPv6 açısından dikkate değer birkaç madde var. Engine 29.0.0, IPv6 yalnızca belirli bir arayüzde kapatıldığında container'ın başlamasını ya da ağ geçidinin seçilmesini engelleyen bir sorunu düzeltti. Aynı sürüm, IPv6 otomatik yapılandırmanın açık olduğu ağlarda container başlatmanın başarısız olmasını önlemek için macvlan ve IPvlan L2 ağlarında açık --gateway olmadan varsayılan ağ geçidi yapılandırmamaya başladı. Engine 29.4.1 ile bir container'ın yalnızca IPv4 ya da yalnızca IPv6 kullanan bir bağlantısının "gateway priority" değeri çift yığınlı bir bağlantıdan yüksekse, o adres ailesi için varsayılan ağ geçidi olarak tek yığınlı bağlantı kullanılır. Engine 29.9.0 ise container'lar arası iletişim (ICC) kapalı bir bridge ağında container'lar arasında IPv6 komşu keşfine IPv4'teki davranışla uyumlu olarak izin verir.

Sık yapılan hatalar

Sık yapılan hatalar: Dokümantasyon aralığını üretimde kullanmak, IPv6 ağı açınca IPv4'ün kapandığını sanmak, Varsayılan bridge'de IPv4'ü kapatmaya çalışmak...
  • Dokümantasyon aralığını üretimde kullanmak: belgelerdeki 2001:db8:: adresleri dokümantasyon için ayrılmıştır; ULA ya da sağlayıcınızın verdiği bir önek kullanın.
  • IPv6 ağı açınca IPv4'ün kapandığını sanmak: IPv4 dağıtımı varsayılan olarak açıktır; yalnızca IPv6 için --ipv4=false gerekir.
  • Varsayılan bridge'de IPv4'ü kapatmaya çalışmak: belgelere göre bu mümkün değildir; kullanıcı tanımlı ağ oluşturun.
  • default-address-pools'a yalnızca IPv6 havuzu yazmak: belgeler yapılandırmanın varsayılan IPv4 havuzlarını da içermesi gerektiğini söyler.
  • IPv6 adresini Compose'ta tırnaksız ve köşeli parantezsiz yazmak: "[::1]:8080:80" biçimi belirsizliği ortadan kaldırır.
  • IPv6 portunun güvenlik duvarında kapalı olduğunu varsaymak: sunucu adresi verilmemiş yayınlar IPv6 adreslerinde de açılır.

Sık Sorulan Sorular

Docker'da IPv6 varsayılan olarak açık mı?

Hayır. IPv6 adres dağıtımı ağ başına --ipv6 ya da Compose'ta enable_ipv6: true ile, varsayılan bridge için daemon.json içindeki "ipv6": true ile açılır. IPv4 ise varsayılan olarak açıktır.

Alt ağ vermezsem hangi IPv6 adresleri kullanılır?

Varsayılan adres havuzlarında IPv6 havuzu yoksa Docker, Engine kimliğinden türetilmiş 40 bitlik Global ID içeren ULA /64 alt ağları kullanır.

IPv6 için NAT kullanmadan container'a doğrudan erişebilir miyim?

Evet; ağı com.docker.network.bridge.gateway_mode_ipv6=routed ile oluşturursunuz. Uzak makinelerin container ağına sunucu üzerinden giden bir yolu olmalıdır ve yine yalnızca yayınlanan portlar erişilebilir olur.

Windows ya da Mac üzerinde Docker IPv6 destekler mi?

IPv6 belgesi, IPv6'nın yalnızca Linux sunucularda çalışan Docker daemon'larında desteklendiğini belirtir.

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 macvlan ve ipvlan · Docker iptables ve UFW · daemon.json yapılandırma