Kontainer tidak menjangkau API khusus VPN? Proksi di host
Terowongan hidup di host, jadi kontainer tidak punya rute ke alamat privat. Publikasikan proksi balik yang sempit dan panggil sebagai host.docker.internal.
Layanan Compose Anda habis waktu terhadap API yang dibuka browser di mesin yang sama tanpa keluhan apa pun. Perbedaan itulah petunjuknya: permintaan yang berhasil keluar dari host dengan terowongan VPN, dan permintaan yang menggantung keluar dari kontainer dengan tumpukan jaringannya sendiri. Tidak ada apa pun di dalam kontainer yang mengetahui rute terowongan, jadi tujuan privat tetap tak terjangkau bagaimanapun nama ditulis. Perbaikannya adalah lompatan yang disengaja melalui host, bukan tabel rute yang lebih pintar.
Mulailah dari mengapa kedua jalur berbeda, lalu putuskan di mana terowongan seharusnya tinggal.
Mengapa host berhasil dan kontainer tidak
Menaikkan terowongan memberi host sebuah antarmuka, sekumpulan rute, dan biasanya entri resolver yang disediakan VPN. Kontainer tidak mewarisi satu pun darinya: ia mulai dengan satu antarmuka di jembatan mesin dan rute bawaan yang menunjuk ke jembatan itu. Rute yang dipasang di host tidak terlihat oleh apa pun yang berjalan di dalam ruang nama itu.
Karena itu gejalanya tampak tidak konsisten, bukan sekadar rusak. Host menyelesaikan nama privat dan terhubung, karena nama dan rute keduanya ada di sana. Kontainer mengirim paketnya ke alamat privat yang tidak dapat dijangkau apa pun di jalur jembatan, dan permintaan habis waktu. Menambahkan nama ke berkas hosts kontainer tidak mengubah apa pun, karena alamatnya sendiri tak terjangkau dari tempat kontainer berada.
Capai host dari dalam kontainer
Proses di dalam kontainer yang memanggil localhost sedang memanggil kontainer. Docker Desktop memublikasikan host.docker.internal sebagai nama yang menunjuk balik ke mesin yang menjalankan mesin kontainer; mesin Linux membiarkannya tak terdefinisi kecuali layanan memintanya, dan itulah yang dilakukan pemetaan di bawah. Dengan itu, aplikasi menargetkan nama dan port alih-alih alamat privat.
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
INTERNAL_API_HOST: "host.docker.internal:8666"Terowongan tetap di sisi host dari lompatan itu, dan port dalam variabel itu adalah port yang akan didengarkan proksi. Kontainer yang kehilangan terowongan kini gagal pada satu lompatan yang diketahui alih-alih mencoba rute yang tidak pernah dimilikinya.
Pilih di mana terowongan tinggal
Ada tiga bentuk yang mungkin untuk layanan Compose yang membutuhkan API privat, dan ketiganya berbeda dalam proses mana yang memiliki terowongan. Klien VPN dapat berjalan di dalam citra kontainer, yang menuntut penyediaan perangkat terowongan dan pemberian kemampuan administrasi jaringan yang menyertainya. Aplikasi dapat berbagi ruang nama jaringan kontainer terowongan terpisah, sehingga kedua proses melihat satu tumpukan dan satu tabel rute. Atau terowongan dapat tetap di host, dengan penerus sempit dari host ke dalam kontainer.
Dua yang pertama menarik berkas profil, perilaku penyambungan ulang, dan kebijakan resolver ke dalam proyek, dan membuat setiap layanan di berkas bergantung pada kesehatan terowongan. Itu terlalu banyak keterkaitan untuk satu panggilan API. Untuk tumpukan pengembangan yang membaca satu titik akhir internal, penerus di sisi host adalah perubahan terkecil yang tetap menyimpan kredensial di tempat tim platform mengelolanya.
Publikasikan satu jalur sempit di host
Mulailah dari apa yang diwarisi penerus: jalankan dengan akun yang memiliki terowongan dan soket keluarnya akan mengambil rute host serta resolver host. Satu blok location nginx mencakup satu jalur.
server {
listen 8666;
location /search/ {
proxy_pass http://10.20.30.40:8090/;
proxy_set_header Host internal-api.example;
proxy_read_timeout 60s;
}
}Perlakukan alamat dan port sebagai pengganti dan masukkan pasangan yang benar-benar didengarkan API. Setiap upstream tambahan berhak atas blok location sendiri, dan setiap blok sebaiknya hanya menerima jalur yang dipanggil layanan ini, agar proksi tidak menjadi pintu umum ke jaringan privat. Ikat pendengar ke alamat jembatan untuk klien yang datang melalui host-gateway, ke loopback hanya ketika klien berbagi ruang nama jaringan host, dan jangan pernah ke 0.0.0.0. Pilih juga port yang masih bebas: nomor yang sudah dipakai membuat proksi tidak mendengarkan sementara kontainer terus habis waktu, yang tak bisa dibedakan dari gangguan jaringan yang Anda mulai.
Port, nama, dan keputusan TLS
Resolusi nama terbelah sama seperti perutean. Pencarian publik kontainer melewati resolver mesin, jadi nama privat yang terselesaikan di host tidak akan terselesaikan di dalam kontainer. Proksilah komponen yang menyelesaikan nama privat itu, karena ia mewarisi resolver host.
TLS adalah keputusan yang ditunda lalu menjelaskan kegagalan berikutnya. Jika proksi meneruskan byte tanpa disentuh, kontainer melihat sertifikat API itu sendiri dan membutuhkan CA internal di penyimpanan kepercayaannya. Jika proksi mengakhiri TLS, kepercayaan itu berpindah ke host dan aplikasi mulai membangun tautan dari tajuk host yang diterimanya. Pilih satu susunan dan terapkan pada setiap sumber daya, karena pengalihan yang diterbitkan susunan lain menunjuk ke nama host yang tidak bisa diselesaikan kontainer.
Verifikasi dari dalam layanan
Kirim permintaan dari kontainer, bukan dari host: curl biasa ke jalur proksi, lalu pemeriksaan kesehatan aplikasi itu sendiri. Ketika proksi menjawab tetapi aplikasi masih gagal, bandingkan tiga hal: URL dasar yang dibangunnya, variabel proksi apa pun di lingkungannya, dan CA yang dipercayainya. Semuanya ada di lingkungan dan log kontainer, dan memperbaiki salah satunya membiarkan VPN tetap tenang.
Tuliskan susunan yang dipilih ke README proyek selagi masih segar. Jika tidak, orang berikutnya yang menabrak batas waktu ini akan menghabiskan sore yang sama untuk menemukan kembali bahwa terowongan tinggal di host.