Mesin nama Docker kini sudah terbongkar tuntas: satu alamat loopback 127.0.0.11, dua sumber jawaban, nama pendek sebagai kontrak, dan alias sebagai nama tambahan. Tetapi memahami mesinnya belum sama dengan mengemudikannya — aplikasi sungguhan tidak saling menyapa dengan ping, melainkan dengan HTTP ke web server dan koneksi TCP ke database. Chapter ini merangkai keduanya menjadi satu alur kerja utuh: sebuah studi kasus tiga container yang saling bekerja lewat nama container tanpa satu pun alamat IP yang kita hafal, diuji dari sisi aplikasi memakai curl dan nc, lalu ditutup dengan arah yang belum pernah kita tempuh — dari container menuju service yang berjalan di mesin host, lengkap dengan demo host.docker.internal dan gateway yang dijanjikan pada Chapter Container DNS.
Menyiapkan Studi Kasus net-latihan #
Panggung kita bangun dari jaringan baru bernama net-latihan — net-aplikasi sengaja kita biarkan berdiri kosong, sehingga pool berikutnya jatuh ke 172.19.0.0/16. Tiga container menempatinya:
$ docker network create net-latihan
$ docker run -d --name web --network net-latihan nginx
$ docker run -d --name db --network net-latihan -e POSTGRES_PASSWORD=rahasia123 postgres:18-alpine
$ docker run -d --name app --network net-latihan alpine:3.20 sleep 1hOutput yang Dihasilkan:
b4a7e2c9f1d53680adb4f7c2e91d5a03f6c8e2b7d9a4f1c5e3b8d6a0f4c7e2b91
f7c2a91b3e55913c4a5f1c6c0a4d8e2b3f4a5b6c7d8e9f0a1b2c3d4e5f60718a
3d7f1a9c5e8b2f6a0c4d9e1b7f3a5c8d6e0b2f9c4a7d5f1e8b3c6a9d0f4e2b5c7
8a2e6c1f9b4d7a3e5c0f8d2b6e9a4c7f1d5b8e3a6c0f9d2b5e8a4c7f1d6b9e3a5cMari kita telaah peran masing-masing container:
web— web server nginx sebagai contoh service HTTP. Portnya sengaja tidak kita terbitkan dengan-pkarena hanya sesama penghuni net-latihan yang perlu mengunjunginya; pembukaan pintu ke dunia luar adalah cerita chapter berikutnya.db— database PostgreSQL dengan password fiktifrahasia123, mendengarkan port 5432 di dalam jaringan. Ia mewakili service yang diakses lewat koneksi TCP murni, bukan HTTP.app— container Alpine polos yang berperan sebagai aplikasi. Perintahsleep 1hsekadar menjaganya hidup selama satu jam agar bisa kita kirim perintah lewatdocker exec.
Pembagian alamat berjalan sesuai ramalan pool: gateway 172.19.0.1 milik host, web menerima 172.19.0.2, db menerima 172.19.0.3, dan app menerima 172.19.0.4. Angka-angka itu tidak perlu kita hafal — dan justru itulah inti chapter ini.
Memasang Perkakas Uji sekaligus Membuktikan Internet #
Container app baru menyimpan busybox; curl dan nc belum tersedia. Kita pasang keduanya dari dalam container:
$ docker exec app apk add curl netcat-openbsdOutput yang Dihasilkan (dipotong):
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/community/x86_64/APKINDEX.tar.gz
(1/7) Installing ca-certificates-bundle (20240226-r0)
...
OK: 9 MiB in 22 packagesPerintah ini sekaligus membayar satu utang bukti dari Chapter Container DNS: unduhan paket dari repositori publik berhasil tanpa satu baris konfigurasi — pertanyaan DNS dl-cdn.alpinelinux.org dikirim ke 127.0.0.11, diteruskan daemon ke DNS upstream host, lalu paket mengalir masuk lewat NAT jaringan bridge. Kedua jalur yang dulu hanya kita baca sebagai diagram kini bekerja untuk kita. Perhatikan juga bahwa nc dipasang dari paket netcat-openbsd, bukan busybox nc bawaan Alpine, karena varian inilah yang mengenal mode pemeriksaan -zv yang akan kita pakai.
Memanggil web dengan curl #
Momen pertama percakapan antar container: app mengakses web berdasarkan namanya, tanpa satu angka IP:
$ docker exec app curl -s http://webOutput yang Dihasilkan (dipotong):
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light; }
body { width: 35em; margin: 0 auto;
...Satu baris perintah itu menuntaskan rantai panjang yang kini bisa kita bedah lengkap:
curlmembaca/etc/resolv.confdan menemukan nameserver127.0.0.11— pintu embedded DNS yang hidup di dalam network namespaceapp.- Pertanyaan “web” dijawab dari tabel internal daemon — bukan dari internet — dengan alamat
172.19.0.2; nama pendek satu label memang wilayah tabel itu. curlmembuka koneksi TCP ke172.19.0.2port 80 — paket bergerak lewat switch virtual net-latihan tanpa NAT dan tanpa keluar host, sehingga latensinya serendah hasilpingpada chapter sebelumnya.- nginx menjawab dengan halaman selamat datang — service HTTP yang tidak pernah kita terbitkan ke host tetap sepenuh hidup bagi sesama penghuni jaringan;
-pmemang urusan dunia luar, bukan urusan tetangga.
Menguji Port TCP dengan nc #
Web server dijawab lewat HTTP; database berkomunikasi lewat TCP pada port 5432. Netcat mode pemeriksaan menguji keberadaan port itu tanpa berbicara protokol PostgreSQL:
$ docker exec app nc -zv db 5432Output yang Dihasilkan:
Connection to db 172.19.0.3 5432 port [tcp/*] succeeded!Kalimat succeeded! menyatakan tiga hal sekaligus: nama db berhasil diterjemahkan menjadi 172.19.0.3, koneksi TCP ke port 5432 berhasil dibuka, dan PostgreSQL benar-benar mendengarkan di sana. Mode -zv langsung menutup koneksi tanpa mengirim data — dirancang khusus untuk menjawab pertanyaan “port ini hidup atau tidak”. Dua galat yang mungkin muncul membawa makna yang berbeda dan menuntut penanganan yang berbeda:
Connection refusedberarti container tujuan hidup dan dapat dijangkau, tetapi tidak ada proses yang mendengarkan port tersebut — layanannya belum selesai menyala, atau portnya memang salah. Arah penelusuran: ke dalam container tujuan.- Kegagalan resolusi nama —
bad addressatauName does not resolveberarti pertanyaan DNS tidak terjawab, biasanya karena container pemanggil dan container tujuan berada di jaringan yang berbeda. Arah penelusuran: keanggotaan network, bukan aplikasi.
Membedakan dua wajah kegagalan ini adalah keterampilan inti troubleshooting jaringan container — kelima resep lengkapnya menunggu chapter penutup section ini.
Aturan Utama: Nama, Bukan IP #
Dua percobaan di atas sama-sama memakai nama container sebagai alamat, dan itu bukan gaya penulisan melainkan aturan praktis: nama kita yang menentukan sendiri, jauh lebih stabil daripada alamat IP yang dibagikan ulang setiap kali container diciptakan.
Bukti terbaiknya adalah membuat ulang container db itu sendiri, lalu memanggil dengan perintah yang persis sama:
$ docker rm -f db
$ docker run -d --name db --network net-latihan -e POSTGRES_PASSWORD=rahasia123 postgres:18-alpine
$ docker exec app nc -zv db 5432Output yang Dihasilkan:
db
c9f4b7e2a1d53860fcb2e7a4d91c5f0a3e8d6b2c9f4a7e1d5b8c3a6f0e2d9b4c7a
Connection to db 172.19.0.5 5432 port [tcp/*] succeeded!Alamat db berpindah dari 172.19.0.3 ke 172.19.0.5, dan tidak satu pun perintah kita perlu berubah — embedded DNS selalu mengarahkan nama ke alamat yang sedang berlaku.
Dari Container ke Host #
Satu arah percakapan masih tersisa: container yang hendak menjangkau service di mesin host — misalnya API development yang berjalan native di laptop pada port 8000. Di Docker Desktop, nama istimewa host.docker.internal tersedia bawaan: dari container Siti, curl http://host.docker.internal:8000 tiba di proses host tanpa konfigurasi apa pun. Di Linux, dua jalur lain menyambut Budi. Jalur pertama: setiap network punya gateway — 172.19.0.1 untuk net-latihan — dan gateway adalah wajah host di jaringan itu:
$ docker exec app ping -c 2 172.19.0.1Output yang Dihasilkan:
PING 172.19.0.1 (172.19.0.1): 56 data bytes
64 bytes from 172.19.0.1: seq=0 ttl=64 time=0.119 ms
64 bytes from 172.19.0.1: seq=1 ttl=64 time=0.104 ms
--- 172.19.0.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet lossJalur kedua memberi Linux nama yang sama dengan Docker Desktop lewat flag --add-host. Nilai istimewa host-gateway digantikan daemon dengan alamat gateway host saat container diciptakan:
$ docker run --rm --add-host=host.docker.internal:host-gateway alpine:3.20 ping -c 2 host.docker.internalOutput yang Dihasilkan:
PING host.docker.internal (172.17.0.1): 56 data bytes
64 bytes from 172.17.0.1: seq=0 ttl=64 time=0.131 ms
64 bytes from 172.17.0.1: seq=1 ttl=64 time=0.118 ms
--- host.docker.internal ping statistics ---
2 packets transmitted, 2 packets received, 0% packet lossPerhatikan alamat yang dijawab: 172.17.0.1 — gateway jaringan default bridge milik container sekali jalan ini, bukan 172.19.0.1 milik net-latihan. Dengan dua jalur ini, arsitektur “container bicara container dengan nama, container bicara host dengan host.docker.internal” dapat dipakai konsisten di semua platform.
Empat Alamat Khusus dalam Satu Tabel #
Seluruh alamat istimewa yang kita temui sepanjang section ini kini telah punya demo masing-masing:
| Alamat | Menunjuk ke | Ketersediaan |
|---|---|---|
127.0.0.11 | embedded DNS server daemon | hanya di user-defined network |
host.docker.internal | mesin host | bawaan Docker Desktop; di Linux lewat --add-host dengan nilai host-gateway |
172.19.0.1 | gateway network — wajah host | setiap bridge network punya satu, mengikuti subnetnya |
127.0.0.1 | loopback container sendiri | selalu ada, di dalam namespace container |
Baris terakhir menyimpan jebakan yang paling sering menjerat pendatang baru: 127.0.0.1 di dalam container bukanlah 127.0.0.1 milik host. Loopback adalah antarmuka milik network namespace — aplikasi di app yang menyambung ke localhost hanya dapat menjangkau proses lain di dalam container app itu sendiri, dan aplikasi di db yang mendengarkan 127.0.0.1 tidak pernah terjangkau oleh tetangganya. Konsekuensi praktisnya menyusul sebagai salah satu kasus utama chapter Troubleshooting Network.
Kita tutup studi kasus dengan membersihkan seluruh panggung:
$ docker rm -f web db app
$ docker network rm net-latihanOutput yang Dihasilkan:
web
db
app
net-latihanPercakapan container ke container kini tuntas dibuktikan: HTTP lewat nama, TCP lewat nama, dan host terjangkau lewat alamat istimewanya. Namun sepanjang chapter ini seluruh dunia luar tetap tidak bisa mengunjungi container web kita — dan memang itu niatnya. Pertanyaan berikutnya sudah menunggu di ambang pintu: bagaimana membuka pintu jaringan privat itu ke luar? Jawabannya adalah pemetaan port dengan flag -p, dan karena sintaks dasarnya sudah kita kuasai pada Chapter Port Publishing, chapter berikutnya memfokuskan diri pada dua hal yang jarang diajarkan: memverifikasi pemetaan secara ujung ke ujung, dan membaca resep diagnosis ketika pintu itu macet.
Referensi #
- Docker Networking Overview — konektivitas antar container, embedded DNS, dan alamat khusus ke host.
- docker container run — CLI Reference
— flag
--network,--add-host, dan--envuntuk studi kasus tiga container. - docker container exec — CLI Reference
— menjalankan
curldanncdi dalam container yang sedang berjalan.