SSD Nodes Learn 🎉 VPS $4.99/aydan başlayan
Rehberler Matt ConnorYazan Matt Connor · Güncellendi 2026-08-07

Docker konteynerlerini VPN uzerinden yonlendirme

Gluetun sidecar kullanirken portlarin neden kayboldugunu ogrenin. Paylasilan ag ad alani mantigini ve calisan Docker Compose yapilandirmasini bu rehberde bulabilirsiniz.

Docker konteynerlerini bir VPN üzerinden yönlendirdiğinizde portların kaybolma nedeni

Docker konteynerlerini bir VPN üzerinden yönlendirmek için bir konteynere tünel bağlantısını verir, ardından diğerlerini network_mode: "service:gluetun" ile onun ağ ad alanına (network namespace) eklersiniz. Bu ekleme işlemi, kullanıcıları şaşırtan kısımdır. Eklenen konteyner artık kendi ağına sahip değildir; bu nedenle yayınladığı portlar ve Docker servis adı da onunla birlikte ortadan kalkar. Portları VPN konteyneri üzerinde yayınlayın; diğer konteynerler uygulamaya VPN konteynerinin adı üzerinden erişecektir.

Eklenen konteyner üzerinde bir ports: bloğu bırakırsanız, Docker konteyneri oluşturmayı tamamen reddeder:

Error response from daemon: conflicting options: port publishing and the container type network mode

Buradaki araç, WireGuard veya OpenVPN üzerinden ticari bir VPN (sanal özel ağ) sağlayıcısına bağlanan ve kendi güvenlik duvarını barındıran bir konteyner olan Gluetun'dur. Ağustos 2026 itibarıyla güncel sürüm v3.41.3'tür. Örneklerde WireGuard ile Mullvad kullanılmıştır; bu nedenle sağlayıcınızdan alınmış bir hesaba ve anahtara ihtiyacınız vardır. Tüneli kendi donanımınızda sonlandırmayı tercih ederseniz, kendi WireGuard sunucunuzu bir VPS üzerinde çalıştırmak karşı ucu oluşturur ve Docker içinde wg-easy bunu bir web arayüzü ile sarmalar.

network_mode: "service:gluetun" gerçekte ne yapar

Her Docker container normalde kendi ağ ad alanına (network namespace) sahiptir: kendi arayüzleri, yönlendirme tablosu, güvenlik duvarı kuralları ve dinleme soketleri. service: modu bu adımı atlar ve container'ı gluetun'un ad alanı içinde başlatır. Tek bir ad alanı, tek bir IP adresi anlamına gelir ve bu durum altı şeyi değiştirir.

  • Uygulamanın kendine ait bir adresi yoktur. Adresi, gluetun'un adresidir.
  • Uygulama hiçbir Docker ağına bağlı değildir, bu nedenle servis adı hiçbir zaman kaydedilmez ve çözümlenmez. Diğer container'lar gluetun kullanmalıdır.
  • Ad alanı içindeki container'lar birbirlerine localhost üzerinden ulaşır.
  • Aynı ad alanındaki iki container aynı portu dinleyemez. Gluetun belgeleri bu konuda nettir: bunun bir geçici çözümü yoktur.
  • Yetenekler (capabilities) bir ad alanına değil, bir container'a aittir. Tünel arayüzünü oluşturduğu için NET_ADMIN ve /dev/net/tun yetenekleri gluetun'da bulunur. Bağlı olan container bunları devralmaz.
  • Compose, bir servisin hem network_mode hem de networks ayarlarını yaptığı dosyaları reddeder. Gluetun'u ağlarınıza bağlayın, uygulama da onunla birlikte çalışacaktır.

Gluetun'u yeniden başlatmak, ona bağlı olan her şeyin bağlantısını keser. Bu belgelenmiş bir davranıştır ve bağlantı koptuğunda gluetun'un çıkış yapmak yerine container içindeki VPN sürecini yeniden başlatmasının nedeni budur. Gluetun'u kendiniz yeniden başlattığınızda veya yeniden oluşturduğunuzda, ona bağlı olan container'ları da yeniden başlatın.

Çalışan compose dosyası

services:
  gluetun:
    image: qmcgaw/gluetun:v3
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    environment:
      - VPN_SERVICE_PROVIDER=mullvad
      - VPN_TYPE=wireguard
      - SERVER_CITIES=Amsterdam
      - TZ=Europe/Amsterdam
    env_file:
      - ./gluetun.env
    volumes:
      - ./gluetun:/gluetun
    ports:
      - 127.0.0.1:8080:8080/tcp
    restart: unless-stopped

  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    network_mode: "service:gluetun"
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
      - WEBUI_PORT=8080
    volumes:
      - ./qbittorrent:/config
      - ./downloads:/downloads
    depends_on:
      gluetun:
        condition: service_healthy
    restart: unless-stopped

:v3 etiketi, v3 serisindeki en yeni kararlı sürümdür. :latest etiketi, geliştirme aşamasındaki master dalının son commit'ini işaret eder; bu nedenle, Salı günü hata ayıklamak istemediğiniz bir makinede :v3 sürümünü sabitleyin.

WEBUI_PORT=8080, yayınlanan port ile eşleşmelidir; çünkü qBittorrent, gluetun'ın namespace'i içinde bağlanır ve yayınlama kuralı, ana makine trafiğini oradaki 8080 numaralı porta gönderir. Birini değiştirip diğerini değiştirmezseniz port hiçbir yanıt vermez. 127.0.0.1:8080:8080, web arayüzünü ana makinenin loopback adresinde tutar. Yalın bir 8080:8080, tüm arayüzlerde yayın yapar ve kendi güvenlik duvarı kuralını yazar; Docker yayınlanan portlarının ufw'yi nasıl doğrudan geçtiği budur.

Servisi ayağa kaldırın ve ardından şu sırayla kontrol edin:

docker compose up -d
docker compose ps
docker compose logs gluetun | tail -30

docker compose ps, gluetun'ı healthy ve qbittorrent'i running olarak göstermelidir. Ardından, diğer her şeye karar veren kontrol olan namespace içinden çıkış adresini doğrulayın:

docker run --rm --network=container:gluetun alpine:3.22 sh -c "apk add wget && wget -qO- https://ipinfo.io"

Bu JSON içindeki ip alanı, VPN sağlayıcınızın adresi olmalıdır. Eğer bu adres sunucunuzun kendi adresi ise, uygulama tünel içinde değildir ve aşağıdakilerin hiçbiri tarif edildiği gibi çalışmayacaktır.

Anahtarları compose dosyasının dışında tutun

gluetun.env kimlik bilgilerini tutar ve git içerisine dahil edilmez:

WIREGUARD_PRIVATE_KEY=wOEI9rqqbDwnN8/Bpp22sVz48T71vJ4fYmFWujulwUU=
WIREGUARD_ADDRESSES=10.64.222.21/32

Her iki değer de sağlayıcınızın hesap panelinden oluşturduğunuz bir WireGuard yapılandırma dosyasından gelir. Dosya izinlerini 600 moduna ayarlayın. Bu yöntemin sağladığı koruma konusunda gerçekçi olun: anahtar deponuzun dışında kalır, ancak docker inspect gluetun Docker soketine erişebilen herkes için tüm ortam değişkenlerini açık metin olarak yazdırır. Docker Compose'da ortam dosyaları ve gizli veriler bölümü daha güçlü seçenekleri ele almaktadır.

Tünel dışındaki bir container'ın içerideki ile iletişimi

Her iki yön de çalışır ve her biri farklı bir isim kullanır. İki container'ın paylaşımlı bir Docker ağına ihtiyacı vardır; bu da bağlı olan container'ın kendi ağı olmadığından gluetun'un ağı anlamına gelir. Docker Compose ağlarının nasıl yapılandırıldığı varsayılanları kapsar.

Dışarıdan içeriye doğru, gluetun'un adını ve uygulamanın dinlediği portu kullanın. Bir reverse proxy container'ı, qBittorrent web arayüzüne gluetun:8080 üzerinden erişir. Bunun için herhangi bir ports: girdisine gerek yoktur, çünkü container'lar arası trafik Docker ağı üzerinde kalır ve hiçbir zaman host portuna temas etmez.

İçeriden dışarıya doğru, diğer container'ın servis adını, örneğin postgres:5432 kullanın. Gluetun, v3.41 sürümünden beri diğer container adlarını kendi namespace'i içinden çözümleyebilmektedir; bu nedenle bir isim çözümlenmiyorsa o sürümü veya daha yenisini sabitleyin.

Gluetun'un güvenlik duvarı, kendisine kimin bağlantı açabileceğine karar verir. Gluetun'un kendi Docker ağından gelen trafiğe izin verilir. Farklı bir alt ağdaki bir istemci, yerel ağınızdaki (LAN) bir dizüstü bilgisayar veya ayrı bir bridge ağındaki bir container, siz o alt ağı tanımlayana kadar engellenir:

FIREWALL_OUTBOUND_SUBNETS=192.168.1.0/24

Belgelenen anlam kesindir: Gluetun'un ve ağ yığınını paylaşan container'ların erişmesine izin verilen, virgülle ayrılmış alt ağlar.

İnternetten gelen gelen bağlantılar ayrı bir sorundur. Bir torrent istemcisinin eşleri (peers) VPN tarafından gelir, bu nedenle host üzerinde 6881 numaralı portu yayınlamak onlar için bir işe yaramaz. Sağlayıcınızdan yönlendirilmiş bir porta ihtiyacınız vardır ve bu portun, VPN sunucusu tarafından gelen portlara izin veren FIREWALL_VPN_INPUT_PORTS içerisinde listelenmesi gerekir. Bu, Docker Compose ile oluşturulan medya yığınlarının çoğunda eksik bırakılan kısımdır.

Kill switch: tünel bağlantısı koptuğunda ne olur

Bu yapı, hata durumlarında karmaşıklığını hak eder. Bağlı olan container'ın ikinci bir rotası yoktur. Makine dışına çıkan tek yolu paylaştığı namespace'tir; bu nedenle tünel kapandığında geri dönülebilecek başka bir yol kalmaz. Gluetun'ın güvenlik duvarı, aynı kuralı diğer taraftan da uygular: giden trafik tünel üzerinden veya VPN sunucusu uç noktasına gider, geri kalan her şey reddedilir. İstemci yeniden bağlanırken paketlerin normal arayüzden sızabileceği bir zaman aralığı oluşmaz.

Gluetun kendi bağlantısını izler. Her dakika HEALTH_ICMP_TARGET_IPS içindeki adreslere (varsayılan olarak 1.1.1.1,8.8.8.8) bir ICMP echo (ping) gönderir. Her beş dakikada bir, varsayılan olarak cloudflare.com:443,github.com:443 olan HEALTH_TARGET_ADDRESSES adresine tam bir TCP ve TLS (transport layer security) bağlantısı gerçekleştirir. Bunlar başarısız olduğunda, container içindeki VPN'i yeniden başlatır ve bunu günlüğe kaydeder:

WARN [vpn] restarting VPN because it failed to pass the healthcheck: periodic check: dialing: dial tcp4: lookup cloudflare.com: i/o timeout

Bağlı container'ın günlüklerini bu düzeni göz önünde bulundurarak okuyun. Uygulama içindeki connection refused, operation not permitted ve i/o timeout gibi satırlar, tünelin kopuk olmasının bir sonucudur, nedeni değildir. Gluetun belgeleri bunu açıkça belirtir, çünkü kullanıcılar sonucu raporlayıp saatlerce bunun peşinden koşarlar.

HEALTH_RESTART_VPN=on varsayılan değerdir ve açık kalmalıdır. Yalnızca belirli bir hatayı ayıklarken kapatın; çünkü bu ayar kapalıyken kopan bir tünel, kendiliğinden tekrar ayağa kalkmaz.

Sıralama: stack'in tünel hazır olmadan başlamasını engelleme

İmaj, bir Docker healthcheck ile birlikte gelir:

HEALTHCHECK --interval=5s --timeout=5s --start-period=10s --retries=1 CMD /gluetun-entrypoint healthcheck

Bu komut, http://127.0.0.1:9999/ adresindeki çalışan gluetun'un sağlık sunucusunu sorgulayan, kısa ömürlü ikinci bir gluetun kopyası çalıştırır. Çalışan bir tünel 200 OK yanıtını verir. Bağlantısı kopmuş bir tünel ise hata metniyle birlikte 500 Internal server error yanıtını döndürür ve container tek bir başarısızlığın ardından sağlıksız (unhealthy) olarak işaretlenir.

condition: service_healthy, bu durumu bekleyen yapıdır. Basit depends_on: [gluetun] ise yalnızca container'ın başlamasını bekler; bu da handshake tamamlanmadan birkaç saniye önce gerçekleşir. Sonuç olarak uygulama, ağ bağlantısı henüz kurulmadan başlar ve genellikle ilk bağlantı denemesinde hata verir. Docker Compose'da Healthcheck'ler bölümü, söz dizimini ve zamanlama alanlarını detaylıca açıklar.

Kullanıcıların sıklıkla karşılaştığı bir sınırlama mevcuttur. Compose, bu koşulu yalnızca container'ı oluşturduğu sırada bir kez değerlendirir. Gluetun daha sonra sağlıksız duruma düşerse uygulamayı durdurmaz veya yeniden başlatmaz. Gluetun'un kendi içindeki otomatik iyileştirme mekanizması bu durumu karşılar; bu nedenle container yerine VPN sürecini yeniden başlatır.

Kurulumu güvenli kabul etmeden önce DNS sızıntısı kontrolü yapın

DNS (domain name system), doğru yapılandırılmış bir tünelde bile sızıntıya neden olabilen bir bileşendir. Gluetun, kendi çözümleyicisini (resolver) isim alanı (namespace) içinde çalıştırır ve sorguları varsayılan olarak DoT (DNS over TLS) üzerinden Cloudflare'e iletir: DNS_UPSTREAM_RESOLVER_TYPE=dot ve DNS_UPSTREAM_RESOLVERS=cloudflare. Her ikisini de değiştirmeyin; böylece sorgularınız şifrelenir ve tünel üzerinden iletilir.

Bunu bozan ayar DNS_UPSTREAM_PLAIN_ADDRESSES değeridir. Kullanıcılar, bir alan adı çözümlenemediğinde ve yönlendiricilerinin veya servis sağlayıcılarının çözümleyicisini kullanmak istediklerinde bu ayara başvururlar. Gluetun belgeleri bunun bedelini açıkça belirtir: Tüm DNS trafiği VPN tüneli üzerinden geçmez ve tünel dışına sızar. Trafiğiniz gizli kalsa da, ziyaret ettiğiniz ana bilgisayar adlarının (hostname) listesi gizli kalmaz. Aynı hatanın WireGuard sürümü WireGuard tüneli üzerinden çözümlenmeyen DNS bölümünde ele alınmıştır.

Test etmek için Gluetun üzerinde HTTPPROXY=on ayarını yapın ve 8888:8888/tcp portunu dışarıya açın, ardından bir tarayıcıyı bu proxy'ye yönlendirerek bir DNS sızıntı testi yükleyin. Sonuç, ev yönlendiricinizi değil, VPN sağlayıcınızı veya Cloudflare'i göstermelidir. Gluetun'un kendi belgeleri, bazı sızıntı testlerinin garip sonuçlar verebileceği konusunda uyarır; çünkü isim alanı içindeki çözümleyici, nihai yanıtı veren sunucudan ziyade yerel bir önbellekleme aracıdır. Yanlış bir ülke veya kendi ISS'nizin çözümleyicisini gerçek bir sızıntı sinyali olarak değerlendirin.

VPN sidecar yanına Tailscale eklemek ve hangisinin öncelikli olduğu

Tailscale, kendi makinelerinize erişmek için WireGuard üzerine inşa edilmiş bir katman ağıdır (overlay network) ve kullanıcılar, yığına (stack) bir yönetici erişim yolu bırakmak için bunu bir sağlayıcı VPN'i ile yan yana çalıştırırlar. Bu ikisi nadiren çakışır; bunun anlaşılması gereken bir nedeni vardır. Tailscale belgeleri varsayılan durumu şöyle belirtir: Bir katman ağı olarak hareket eder, yalnızca Tailscale çalıştıran cihazlar arasındaki trafiği yönlendirir ve genel internet trafiğinize dokunmaz.

Bu nedenle cevap, tek bir ayara bağlıdır.

  • Kendi container'ı içinde Tailscale, varsayılan yapılandırma: Uygulamanın giden trafiğini asla görmez. Trafiğin tamamını Gluetun taşır. Tailscale, uygulamaya tıpkı dışarıdaki başka bir container gibi gluetun:8080 üzerinden ulaşır.
  • Gluetun'ın namespace'ine network_mode: "service:gluetun" ile eklenmiş Tailscale: Namespace ile birlikte yetenekler (capabilities) gelmediği için kendi cap_add, net_admin ve net_raw değerlerine ihtiyaç duyar. Varsayılan userspace ağ modunda TS_USERSPACE açık olduğunda, tailscaled hiçbir arayüz oluşturmaz ve SOCKS5 veya HTTP proxy olarak çalışır; bu yüzden yönlendirmeyi değiştiremez. Gluetun her şeyi taşımaya devam eder.
  • Aynı durum, TS_USERSPACE=false ile: tailscaled bir tünel cihazı oluşturur ve rotalar ekler, ancak bu yalnızca 100.64.0.0/10 tailnet aralığı ve TS_ROUTES ile duyurduğunuz alt ağ rotaları içindir. Genel trafik yine Gluetun üzerinden çıkar.
  • Yukarıdakilerden herhangi biri seçili bir çıkış düğümü (exit node) ile kullanıldığında, sudo tailscale set --exit-node=<exit-node-ip>: Tailscale varsayılan rotayı sahiplenir ve öncelikli olur. Bunu Gluetun ile birleştirmeyin. Tek bir varsayılan rota olur ve tek bir sahibi bulunur.

Tünel içinde Tailscale çalıştırıldığında yan etki olarak bir durum gözlemlenir. Eşler (peers), VPN sağlayıcısının adresini görür, bu yüzden bağlantının daha sık rölelere (relays) düşmesini bekleyebilirsiniz. Bu durum gerçekleştiğinde tailscale status, bir eşin yanında direct yerine relay "..." gösterir. Bağlantı çalışır ancak daha yavaştır. Eğer tek ihtiyacınız olan şey katman ağı ise, yalın WireGuard ile Tailscale arasındaki fark daha iyi bir başlangıç noktasıdır.

Neler bozulur ve göreceğiniz hata mesajları

Docker, uygulama container'ını oluşturmayı reddediyor. Error response from daemon: conflicting options: port publishing and the container type network mode hatası, bağlı servis üzerinde bir ports: bloğunun hala mevcut olduğu anlamına gelir. Bu bloğu gluetun'a taşıyın.

Compose tüm dosyayı reddediyor. Bir servis aynı anda hem network_mode hem de networks ayarlarını içeremez. Ağ yapılandırmasını gluetun üzerine alın.

Başka bir container uygulamayı çözümleyemiyor. curl: (6) Could not resolve host: qbittorrent beklenen bir davranıştır; çünkü bağlı container hiçbir ağa katılmamış ve bir isim kaydı oluşturmamıştır. gluetun ve ilgili portu kullanın.

İkinci bağlı container başlamıyor. Aynı namespace içindeki iki süreç aynı portu dinleyemez; kaybeden süreç adresin kullanımda olduğuna dair hata verir. Uygulamanın iç portunu değiştirin veya ikinci bir gluetun çalıştırın.

Gluetun'a müdahale ettikten sonra uygulamanın ağ bağlantısı kesildi. Gluetun'u yeniden başlatmak veya yeniden oluşturmak, ona bağlı olan her şeyin bağlantısını koparır. Bu container'ları yeniden başlatın.

Küçük sayfalar yükleniyor ancak büyük sayfalar takılıyor. Bu durum MTU (maximum transmission unit) ile ilgilidir. Tünel ek yük getirir ve yol üzerindeki bir cihaz, hata mesajı göndermeden büyük paketleri düşürür. WIREGUARD_MTU değerini düşürün, önce 1400, ardından 1320 değerlerini deneyin.

Gluetun sağlıklı (healthy) durumuna geçmiyor. Başlangıç kontrolü ilk şüphelileri belirtir: WARN [vpn] restarting VPN because it failed to pass the healthcheck: startup check: dialing: dial tcp4: lookup cloudflare.com: i/o timeout. Anahtarın süresinin dolup dolmadığını, sunucu listesinin güncel olup olmadığını ve ana makine güvenlik duvarınızın giden UDP trafiğini engelleyip engellemediğini kontrol edin.

FAQ

Konteynerimin yayınlanan portları neden Gluetun arkasında çalışmayı durdurdu?

Çünkü network_mode: "service:gluetun", konteyneri gluetun'ın ağ ad alanı (network namespace) içine yerleştirir ve bir ad alanı tek bir IP adresine ve tek bir dinleme portu kümesine sahiptir. Uygulama dinlemeye devam eder ancak yayınlama kuralının, ad alanına sahip olan konteyner üzerinde tanımlanması gerekir. ports: listesini gluetun servisine taşıyın. Eğer bu listeyi bağlı serviste bırakırsanız, Docker bunu oluşturmayacaktır: Error response from daemon: conflicting options: port publishing and the container type network mode.

VPN tüneli içindeki bir konteynere, dışındaki bir konteynerden nasıl erişirim?

Gluetun'ın servis adını ve uygulamanın dinlediği portu kullanın; örneğin gluetun:8080. Bağlı konteynerin kendine ait bir Docker ağı yoktur, bu nedenle kendi adı hiçbir zaman çözümlenmez. Konteynerler arası trafik için herhangi bir port yayınlamaya gerek yoktur. Diğer yönde ise, ad alanı içindeki bir konteyner, dışarıdaki bir konteynere Gluetun v3.41 ve sonraki sürümlerde postgres:5432 gibi servis adıyla erişir. Yerel ağınızdaki bir dizüstü bilgisayar gibi farklı bir alt ağdaki istemci, siz o alt ağı FIREWALL_OUTBOUND_SUBNETS içine ekleyene kadar gluetun güvenlik duvarı tarafından engellenir.

VPN bağlantısı koptuğunda Gluetun bir kill switch görevi görür mü?

Evet, hem de aynı anda iki nedenden dolayı. Bağlı konteynerin paylaşılan ad alanındaki rota dışında başka bir rotası yoktur, bu nedenle tünel kapandığında makine dışına çıkacak bir yolu kalmaz. Gluetun'ın güvenlik duvarı da giden trafiğe yalnızca tünel üzerinden ve VPN sunucusu uç noktasına doğru izin verir. Gluetun, her bağlı konteynerin ağ bağlantısı kesileceği için çıkış yapmak yerine VPN'i dahili olarak yeniden başlatır ve WARN [vpn] restarting VPN because it failed to pass the healthcheck günlüğünü kaydeder.

Tailscale ve Gluetun aynı yığında: giden trafiği hangisi taşır?

Biri hariç tüm yapılandırmalarda Gluetun taşır. Tailscale varsayılan olarak yalnızca tailnet'inizdeki cihazlar arasındaki trafiği yönlendirir ve genel trafiğe müdahale etmez. Konteyner imajının varsayılan kullanıcı alanı (userspace) modunda hiçbir arayüz oluşturmaz, bu nedenle yönlendirmeyi etkileyemez. TS_USERSPACE=false ile yalnızca 100.64.0.0/10 ve duyurduğunuz alt ağlar için rotalar kurar. İstisna ise bir çıkış düğümüdür (exit node): sudo tailscale set --exit-node=<exit-node-ip>, Tailscale'i varsayılan rota haline getirir ve bu durumda Tailscale öncelikli olur. İkisini üst üste yığmak yerine, varsayılan rotayı yönetecek tek bir ürün seçin.