Compose hizmetiniz, aynı makinedeki tarayıcının hiç şikâyet etmeden açtığı bir API karşısında zaman aşımına uğruyor. Bu fark ipucudur: çalışan istek VPN tünelli bir host’tan çıkar, askıda kalan istek ise kendi ağ yığını olan bir konteynerden çıkar. Konteynerin içinde hiçbir şey tünelin rotalarını bilmez, bu yüzden adres nasıl yazılırsa yazılsın özel hedef erişilemez kalır. Çözüm, host üzerinden bilinçli bir sıçramadır; daha akıllı bir yönlendirme tablosu değil.

İki yolun neden farklı olduğuyla başlayın, sonra tünelin nerede yaşaması gerektiğine karar verin.

Host neden çalışır da konteyner çalışmaz

Tüneli ayağa kaldırmak host’a bir arayüz, bir dizi rota ve genellikle VPN’in sağladığı bir çözümleyici kaydı verir. Konteyner bunların hiçbirini devralmaz: motorun köprüsünde tek bir arayüzle ve o köprüyü gösteren varsayılan rotayla başlar. Host’ta kurulu rotalar, o ad alanı içinde çalışan hiçbir şey tarafından görülemez.

Bu yüzden belirtiler yalnızca bozuk değil, tutarsız görünür. Host özel adı çözer ve bağlanır, çünkü orada hem ad hem de rota vardır. Konteyner paketini köprü yolunda hiçbir şeyin ulaşamayacağı özel bir adrese gönderir ve istek zaman aşımına uğrar. Adı konteynerin hosts dosyasına eklemek hiçbir şeyi değiştirmez, çünkü adresin kendisi konteynerin bulunduğu yerden erişilemezdir.

Host’a konteynerin içinden ulaşın

Konteyner içindeki bir süreç localhost adresini arıyorsa konteyneri arıyordur. Docker Desktop host.docker.internal adını motoru çalıştıran makineye geri işaret eden bir ad olarak yayınlar; Linux motorları hizmet istemedikçe onu tanımsız bırakır ve aşağıdaki eşleme tam olarak bunu yapar. Bununla uygulama özel adres yerine bir adı ve bir bağlantı noktasını hedefler.

services:
  app:
    extra_hosts:
      - "host.docker.internal:host-gateway"
    environment:
      INTERNAL_API_HOST: "host.docker.internal:8666"

Tünel, sıçramanın host tarafında kalır ve o değişkendeki bağlantı noktası proxy’nin dinleyeceği noktadır. Tüneli kaybeden konteyner artık hiç sahip olmadığı bir rotayı denemek yerine bilinen tek bir sıçramada başarısız olur.

Tünelin nerede yaşadığını seçin

Özel bir API’ye ihtiyaç duyan Compose hizmeti için üç biçim mümkündür ve bunlar tünelin hangi sürece ait olduğuyla ayrılır. Bir VPN istemcisi konteyner imajının içinde çalışabilir; bu, bir tünel aygıtının açığa çıkarılmasını ve beraberindeki ağ yönetimi yeteneğinin verilmesini gerektirir. Uygulama ayrı bir tünel konteynerinin ağ ad alanını paylaşabilir, böylece iki süreç de tek bir yığın ve tek bir yönlendirme tablosu görür. Ya da tünel host’ta kalabilir; host’tan konteynere dar bir ileticiyle.

İlk ikisi profil dosyalarını, yeniden bağlanma davranışını ve çözümleyici ilkesini projeye çeker ve dosyadaki her hizmeti tünelin sağlığına bağımlı kılar. Tek bir API çağrısı için bu fazla bağlaşımdır. Tek bir iç uç noktayı okuyan bir geliştirme yığını için host tarafındaki iletici, kimlik bilgilerini platform ekibinin yönettiği yerde tutan en küçük değişikliktir.

Host’ta tek bir dar yol yayınlayın

İleticinin devraldığı şeyle başlayın: onu tünelin sahibi olan hesapla çalıştırın; giden soketleri host’un rotalarını ve host’un çözümleyicisini devralır. Tek bir nginx location bloğu tek bir yolu kapsar.

server {
    listen 8666;
    location /search/ {
        proxy_pass http://10.20.30.40:8090/;
        proxy_set_header Host internal-api.example;
        proxy_read_timeout 60s;
    }
}

Adresi ve bağlantı noktasını yerine konabilir şeyler olarak görün ve API’nin gerçekten dinlediği çifti koyun. Her ek upstream kendi location bloğunu hak eder ve her blok yalnızca bu hizmetin çağırdığı yolları kabul etmelidir; böylece proxy özel ağa açılan genel bir kapıya dönüşmez. Dinleyiciyi host-gateway üzerinden gelen istemciler için köprü adresine, yalnızca istemci host’un ağ ad alanını paylaştığında loopback’e bağlayın ve asla 0.0.0.0’a bağlamayın. Henüz boş olan bir bağlantı noktası da seçin: çoktan alınmış bir numara proxy’yi dinlemez bırakırken konteyner zaman aşımına uğramaya devam eder; bu da başladığınız ağ arızasından ayırt edilemez.

Bağlantı noktaları, adlar ve TLS kararı

Ad çözümlemesi yönlendirmeyle aynı biçimde bölünür. Konteynerin genel sorguları motorun çözümleyicisinden geçer, bu yüzden host’ta çözülen özel bir ad konteynerin içinde çözülmez. Özel adı çözen bileşen proxy’dir, çünkü host’un çözümleyicisini devralır.

TLS, ertelenen ve sonra bir sonraki arızayı açıklayan karardır. Proxy baytları dokunmadan iletirse konteyner API’nin kendi sertifikasını görür ve güven deposunda iç CA’ya ihtiyaç duyar. Proxy TLS’i sonlandırırsa bu güven host’a geçer ve uygulama aldığı host başlığından bağlantılar kurmaya başlar. Tek bir düzen seçin ve bunu her kaynağa uygulayın, çünkü diğerinin yayımladığı yönlendirme konteynerin çözemeyeceği bir ana bilgisayar adına işaret eder.

Hizmetin içinden doğrulayın

İsteği host’tan değil konteynerden gönderin: proxy yoluna karşı sade bir curl, ardından uygulamanın kendi sağlık kontrolü. Proxy yanıt verip uygulama hâlâ başarısız olursa üç şeyi karşılaştırın: kurduğu temel URL, ortamındaki herhangi bir proxy değişkeni ve güvendiği CA. Hepsi konteynerin ortamında ve günlüklerindedir ve bunlardan herhangi birini düzeltmek VPN’e dokunmaz.

Seçilen düzeni henüz tazeyken projenin README dosyasına yazın. Yoksa bu zaman aşımına çarpan bir sonraki kişi tünelin host’ta yaşadığını yeniden keşfetmekle aynı öğleden sonrayı geçirir.

İlgili makaleler