Peta konsep pada Chapter Konsep Networking Docker memperkenalkan docker0, veth pair, dan NAT masquerade sebagai tiga tokoh di balik layar — sekarang saatnya ketiganya kita jumpai secara langsung. Jaringan yang akan kita bedah adalah jaringan yang dipakai setiap container sejak awal course tanpa kita minta: bridge default. Kita akan melihatnya dari tiga sudut sekaligus — dari luar lewat docker network inspect, dari dalam lewat ip addr milik container, dan dari jauh lewat ping ke 8.8.8.8 yang membuktikan masquerade bekerja. Chapter ini ditutup dengan satu kelemahan default bridge yang paling terkenal, kelemahan yang akan mengubah cara kita menjalankan container untuk sisa course ini.
Tiga Jaringan yang Selalu Ada #
Instalasi Docker yang bersih selalu membawa tiga jaringan bawaan. Perintah berikut mendaftarkannya:
$ docker network lsOutput yang Dihasilkan:
NETWORK ID NAME DRIVER SCOPE
9e7d2c4b1a8f bridge bridge local
3f8a6d2c9e4b host host local
7c1e9a3d5f2b none null localMari kita telaah kolom-kolomnya satu per satu:
NETWORK ID— pengenal 12 karakter heksadesimal, padananCONTAINER IDpadadocker ps; bentuk penuhnya 64 karakter dan akan tampil padadocker network inspect.NAME— nama jaringan; ketiga nama ini adalah nama tetap yang sama di semua instalasi Docker, sehingga cocok dipakai sebagai rujukan lintas mesin.DRIVER— driver yang membangun jaringan; perhatikan jaringan bernamanonejustru tercatat dengan drivernull, bukannone— istilah “null” memang istilah teknis untuk driver yang tidak membangun konektivitas apa pun, dan bedah lengkapnya menunggu di Chapter None Network.SCOPE— cakupan jaringan;localberarti jaringan hanya hidup pada host ini, berbeda dengan cakupanswarmyang membentang lintas host.
Setiap docker run tanpa flag --network menempelkan container ke jaringan bridge yang pertama itu. Seluruh demo kita sejak Section Dasar Docker CLI — container web, db-katalog, hingga latihan volume — diam-diam berbagi satu switch virtual yang sama. Saatnya kita buka kubahnya.
Bedah docker network inspect bridge #
Metadata lengkap jaringan default tersimpan dan bisa dibaca dengan satu perintah:
$ docker network inspect bridgeOutput yang Dihasilkan:
[
{
"Name": "bridge",
"Id": "9e7d2c4b1a8f4c6e8a0b2d4f6a8c0e2b4d6f8a0c2e4b6d8f0a2c4e6b8d0f2a4c",
"Created": "2026-10-13T08:12:09.418273521Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]Waktu Created menunjukkan pukul 08:12 pagi — daemon Docker Budi menyala sejak itu, dan jaringan bridge lahir bersamanya. Mari kita telaah bagian-bagian terpentingnya:
IPAM.Config— pengaturan alamat: subnet172.17.0.0/16dengan gateway172.17.0.1. Inilah angka-angka yang selama ini hanya kita lihat dari sisi container;172.17.0.1adalah alamat docker0 sendiri, bendahara alamat bagi semua container yang tercolok.com.docker.network.bridge.name: docker0— nama interface bridge di namespace host; opsi ini menghubungkan jaringan bernamabridgedengan interfacedocker0yang kita kenal dari diagram topologi chapter sebelumnya.com.docker.network.bridge.enable_ip_masquerade: true— sakelar NAT yang kita bahas sebagai konsep kini terlihat sebagai baris konfigurasi nyata; nilainyatrue, dan itulah alasan container bisa menjangkau internet.Containerskosong — daftar penghuni jaringan saat ini; pukul ini tidak ada container yang hidup di mesin latihan kita, sehingga objeknya kosong — kita akan mengisinya lagi segera.
Stack Jaringan Sebuah Container di Bridge Default #
Sekarang kita masuk ke dalam rumah container itu sendiri. Satu container Alpine sekali jalan cukup untuk memotret seluruh isi network namespace-nya:
$ docker run --rm alpine:3.20 ip addrOutput yang Dihasilkan:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft foreverMari kita telaah baris demi baris:
lodengan127.0.0.1/8— loopback bawaan setiap network namespace; aplikasi di dalam container yang menyambung kelocalhostmendarat di interface ini, bukan di loopback host.eth0@if15— kartu jaringan utama container; akhiran@if15adalah nomor interface pasangan di sisi host, jejak veth pair yang dijelaskan pada Chapter Konsep Networking Docker — kabel virtual dua ujung itu terbaca namanya di sini.inet 172.17.0.2/16— alamat pertama yang dibagikan bendahara docker0 setelah alamat gateway172.17.0.1diambil sang bridge; container ini menjadi penghuni pertama, jadi kebagian nomor dua.- MAC
02:42:ac:11:00:02— alamat hardware kartu virtual ini menyimpan rahasia kecil yang menarik untuk dibedah, dan bedahnya ada di uraian berikutnya.
MAC address tersebut tidak dipilih secara acak. Docker menyusunnya dari dua bagian: prefiks 02:42 menandai alamat yang dikelola secara lokal (locally administered), lalu empat byte terakhir adalah alamat IP container ditulis dalam heksadesimal — ac adalah 172, 11 adalah 17, 00 adalah 0, dan 02 adalah 2, sehingga ac:11:00:02 terbaca sebagai 172.17.0.2. Dengan menyandikan alamat IP ke dalam MAC, Docker memastikan tidak ada dua container di bridge yang sama yang kebetulan memakai MAC identik.
Menembus ke Internet: Masquerade Bekerja #
Teori NAT masquerade sudah kita bangun di chapter sebelumnya; sekarang kita uji dengan target yang paling mudah dikenali:
$ docker run --rm alpine:3.20 ping -c 2 8.8.8.8Output yang Dihasilkan:
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=114 time=13.2 ms
64 bytes from 8.8.8.8: seq=1 ttl=113 time=12.8 ms
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 12.8/13.0/13.2 msMari kita telaah apa yang barusan terjadi di balik dua baris 64 bytes itu:
- Container tidak punya alamat publik — namespace container hanya memegang
172.17.0.2, alamat privat yang tidak dikenal router internet; paketnya sampai ke8.8.8.8karena kernel host menulis ulang alamat sumbernya menjadi192.168.1.15lewat aturan masquerade pada opsienable_ip_masqueradeyang barusan kita lihat di inspect. - Balasan menemukan jalan pulang —
8.8.8.8membalas ke192.168.1.15, dan tabel terjemahan di kernel host mengarahkan balasan itu kembali ke172.17.0.2di dalam namespace container; proses ping sama sekali tidak menyadari adanya penerjemahan. ttl=114— waktu hidup paket terhitung dari server Google ke host Budi; angka ini menunjukkan paket melintasi belasan hop router sebelum tiba, dan seluruh perjalanan pulangnya diterjemahkan dua kali oleh NAT tanpa satu paket pun tersesat.
Port Publishing di Balik Layar #
Jalur keluar ke internet kini terbukti; jalur masuk dari luar adalah cerita yang sudah pernah kita kerjakan. Flag -p 8080:80 pada Chapter Port Publishing bekerja dengan menulis aturan DNAT di kernel host: paket yang tiba di port 8080 milik host ditulis ulang tujuannya menjadi 172.17.0.2:80 sebelum diteruskan ke container. Kita replay mekanismenya secara singkat:
$ docker run -d --name web -p 8080:80 nginxOutput yang Dihasilkan:
f7c2a91b3e55913c4a5f1c6c0a4d8e2b3f4a5b6c7d8e9f0a1b2c3d4e5f60718a$ curl -sI localhost:8080Output yang Dihasilkan:
HTTP/1.1 200 OK
Server: nginx/1.29.4
Date: Tue, 13 Oct 2026 18:15:03 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Mon, 12 Oct 2026 09:24:17 GMT
Connection: keep-alive
ETag: "6779f57d-267"
Accept-Ranges: bytesRespons 200 OK itu menempuh dua lapis penerjemahan: dari port 8080 di host menuju port 80 di container lewat DNAT, lalu balasannya diterjemahkan balik. Perlu dicatat bahwa dari sudut pandang nginx, klien yang datang tampak berasal dari 172.17.0.1 — alamat docker0 — persis seperti yang kita saksikan pada baris-baris access log di Chapter Melihat Log Container. Port publishing dan NAT masquerade sesungguhnya adalah dua arah dari mesin penerjemahan alamat yang sama.
Kelemahan Default Bridge: Tanpa DNS #
Sampai di sini default bridge tampak sempurna — konektivitas antar container, jalan keluar ke internet, dan pintu masuk dari luar semuanya bekerja. Kelemahannya baru muncul ketika kita meminta hal yang paling wajar di dunia aplikasi: memanggil tetangga dengan nama. Kita siapkan dua container yang saling bekerja sama, keduanya di jaringan bawaan yang sama:
$ docker run -d --name web-a nginxOutput yang Dihasilkan:
2d9f4c7b1a5e6b8d0f2a4c6e8a1c3e5b7d9f0a2c4e6b8d0f1a3c5e7b9d0f2a4c$ docker run -d --name app alpine:3.20 sleep 1hOutput yang Dihasilkan:
6c1e8a4b2f9d0b2d4f6a8c1e3b5d7f9a0c2e4b6d8f0a2c4e6b8d0f1a3c5e7b9dKedua container kini menjadi tetangga terdekat di bridge yang sama — web masih memegang 172.17.0.2 dari recap port publishing, web-a menempati 172.17.0.3, dan app menempati 172.17.0.4. Dari dalam app, kita coba menyapa web-a dengan namanya:
$ docker exec app ping -c 2 web-aOutput yang Dihasilkan:
ping: bad address 'web-a'Sapaan itu ditolak mentah-mentah. Namun konektivitasnya sendiri tidaklah rusak — buktinya, memanggil alamat IP milik web-a secara langsung tetap berhasil:
$ docker exec app ping -c 2 172.17.0.3Output yang Dihasilkan:
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.089 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.117 ms
--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.089/0.103/0.117 msMari kita telaah pasangan keberhasilan dan kegagalan di atas:
bad addressberarti nama tidak diterjemahkan — pesan galat ini keluar saat proses resolusi nama gagal, sebelum satu paket pun dikirim; default bridge tidak menyediakan server DNS untuk nama container, sehinggaweb-atidak pernah berubah menjadi172.17.0.3di mataapp.- Ping lewat IP berhasil mulus —
timedi bawah 0.2 milidetik menandakan perjalanan lurus lewat docker0 tanpa keluar host; masalahnya murni soal nama, bukan soal jalur. - Mekanisme
--linkadalah warisan lama — pada masa lalu, flag--linkpadadocker runbisa menyuntikkan entri nama antar container di default bridge; mekanisme itu telah ditinggalkan dan tidak boleh dipakai lagi pada instalasi Docker modern, sehingga default bridge benar-benar tanpa DNS.
Jalan keluarnya terlihat menggoda: catat saja alamat IP-nya. Jalan itu adalah jebakan.
Sebelum pindah, kita bersihkan meja latihan dari chapter ini:
$ docker rm -f web web-a appOutput yang Dihasilkan:
web
web-a
appDefault bridge telah menunjukkan wibawa dan cacatnya sekaligus: konektivitas dan NAT bekerja tanpa komando, tetapi nama container tidak bisa dipanggil. Sebelum kita membangun jaringan sendiri yang memperbaiki cacat itu, ada satu mode jaringan yang bergerak ke arah sebaliknya — melepas isolasi sepenuhnya dan menumpang langsung pada stack jaringan host. Chapter Host Network membedah mode paling agresif ini, lengkap dengan konsekuensi yang wajib dipahami sebelum memakainya.
Referensi #
- Bridge Network Driver
— perilaku default bridge, opsi
com.docker.network.bridge.namedan sekerabatnya, serta batasannya. - docker network inspect — referensi field IPAM, Containers, dan Options pada output inspect.
- docker network ls — format kolom NETWORK ID, NAME, DRIVER, dan SCOPE.