Kegagalan jaringan pada Docker Desktop sering kali bermanifestasi sebagai container yang berjalan normal tanpa error log, namun port yang dipublikasikan tidak dapat diakses dari host (silent packet drop atau connection refused). Masalah ini umumnya dipicu oleh konflik rute antara virtualisasi jaringan Docker Desktop (VPNKit atau gVisor stack) dan tunnel VPN korporat yang menerapkan kebijakan routing ketat.

Arsitektur Virtualisasi Jaringan: VPNKit vs gVisor

Docker Desktop berjalan di dalam VM Hyper-V/WSL2 (Windows) atau Virtualization Framework (macOS). Agar container di dalam VM dapat berkomunikasi dengan host dan jaringan eksternal tanpa memerlukan hak akses root raw socket di host OS, Docker Desktop menggunakan layer proxy pengguna (user-space networking).

  • VPNKit: Mengintercept traffic Ethernet virtual dan menerjemahkannya menjadi socket call TCP/UDP standar di host OS. VPNKit bertindak sebagai proxy layer-4. Ketika VPN korporat memanipulasi routing table host atau mematikan fitur split tunneling, traffic balik dari host ke subnet internal Docker sering diblokir.
  • gVisor netstack: Diimplementasikan pada versi Docker Desktop yang lebih baru untuk menggantikan VPNKit dalam menangani virtual networking dengan performa dan kompatibilitas yang lebih tinggi. Meski lebih stabil, modifikasi MTU atau DNS proxy dari VPN pihak ketiga tetap dapat menyebabkan drop paket data TCP SYN secara hening.

Investigasi: Packet Capture dan Logging Virtual Interface

Langkah awal investigasi adalah memverifikasi apakah paket benar-benar mencapai container atau tertahan di layer proxy host.

1. Cek Listening Socket pada Host

Pastikan proses Docker Desktop benar-benar membuka socket binding di host:

# macOS
lsof -nP -iTCP:8080 -sTCP:LISTEN

# Windows (PowerShell)
Get-NetTCPConnection -LocalPort 8080 -State Listen

Jika port terbuka di host tetapi curl mengembalikan timeout, traffic terputus antara host proxy dan VM Linux backend.

2. Trace Paket dari Dalam Container dan VM

Masuk ke namespace jaringan VM untuk menangkap traffic yang masuk melalui interface virtual:

# Akses debug shell VM Docker Desktop
docker run -it --rm --privileged --pid=host alpine nsenter -t 1 -m -u -n -i sh

# Dump traffic pada interface eth0/docker0 di dalam VM
tcpdump -nn -i any port 8080

Kirim request dari host: curl -v http://localhost:8080. Jika tcpdump di dalam VM tidak mencatat adanya paket SYN, VPN korporat atau firewall host telah memblokir alur loopback bridge.

Mitigasi dan Rollback Konfigurasi Engine Daemon

Konflik subnet sering terjadi jika IP default Docker (172.17.0.0/16) tumpang tindih dengan subnet intranet VPN korporat. Konfigurasikan file daemon.json untuk memindahkan pool address internal Docker ke segmen yang aman.

Lokasi file:

  • macOS: ~/.docker/daemon.json
  • Windows: C:\ProgramData\Docker\config\daemon.json

Terapkan konfigurasi rollback subnet dan alokasi bridge berikut:

{
  "bip": "192.168.200.1/24",
  "default-address-pools": [
    {
      "base": "192.168.201.0/20",
      "size": 24
    }
  ],
  "dns": ["1.1.1.1", "8.8.8.8"]
}

Jika masalah terjadi setelah mengaktifkan fitur eksperimental di UI Docker Desktop, matikan opsi Use containerd for pulling and storing images dan ubah network engine kembali ke stack stabil pada menu Settings > General > Choose network stack (VPNKit) atau matikan gVisor sesuai kebutuhan.

Otomasi: Skrip Health Check Jaringan Lokal

Untuk mendeteksi kegagalan rute saat beralih koneksi VPN, gunakan skrip health check berikut. Skrip menguji path loopback port forwarding dan akses keluar via DNS.

#!/usr/bin/env bash
set -euo pipefail

TEST_PORT=9998
CONTAINER_NAME="docker-net-canary"

cleanup() {
    docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
}
trap cleanup EXIT

cleanup

# 1. Jalankan ephemeral container
docker run -d --name "$CONTAINER_NAME" -p "${TEST_PORT}:80" nginx:alpine >/dev/null

# 2. Verifikasi local port forwarding via Host
sleep 2
if ! curl -s --max-time 3 "http://127.0.0.1:${TEST_PORT}" >/dev/null; then
    echo "[FAIL] Ingress port forwarding rusak. Terjadi silent drop pada layer VPNKit/gVisor."
    exit 1
fi

# 3. Verifikasi Egress Network & DNS Resolution dari Container
if ! docker exec "$CONTAINER_NAME" ping -c 2 -W 3 1.1.1.1 >/dev/null 2>&1; then
    echo "[FAIL] Egress connectivity drop. Periksa intervensi routing tabel VPN."
    exit 2
fi

echo "[OK] Jaringan Docker Desktop dan port forwarding berfungsi normal."

Jalankan skrip ini segera setelah menyambungkan workstation ke VPN korporat untuk memvalidasi ketersediaan binding port lokal.