Bridge default memberi kita isolasi yang rapi: container hidup di rumahnya sendiri, berbicara lewat switch virtual, dan keluar rumah lewat NAT. Arah yang belum kita jelajahi adalah arah yang berlawanan total — melepas rumah itu sama sekali dan menumpang langsung pada stack jaringan milik host. Docker menyediakan mode ini lewat flag --network host, dan mode ini mengubah hampir semua aturan main yang kita pelajari sejauh ini: port tidak perlu diterbitkan, tabel routing yang dipakai adalah tabel routing host, dan kartu jaringan yang dilihat container adalah kartu jaringan sungguhan Budi. Chapter ini membedah konsekuensi-konsekuensinya satu per satu, membandingkannya dengan mode bridge, dan menutup dengan batas platform yang sering menjebak pengguna Docker Desktop.

Menempel Langsung pada Stack Jaringan Host #

Flag --network host memerintahkan Docker untuk tidak membuat network namespace terpisah bagi container. Container tetap mendapat isolasi namespace lain — PID, mount, UTS tetap terpisah seperti biasa — tetapi untuk urusan jaringan, container menumpang sepenuhnya pada namespace jaringan host. Konsekuensinya tiga, dan ketiganya mengubah cara kita bekerja:

  1. Tanpa -p — setiap port yang dibind aplikasi di dalam container adalah port host secara langsung; nginx yang mendengarkan port 80 menempati port 80 milik host tanpa perantara DNAT apa pun.
  2. Port bentrok dengan proses host — container kini berbagi satu ruang port dengan seluruh proses di host; bila sshd host sedang memegang port 22, container yang mencoba port yang sama akan gagal bind, dan sebaliknya.
  3. Permukaan jaringan host terbuka — container melihat semua interface host dan dapat bind pada alamat mana pun di antaranya; isolasi jaringan yang selama ini kita andalkan lenyap, sehingga aplikasi di dalam container harus benar-benar dipercaya.

Biar konsekuensi pertama terlihat nyata, kita jalankan nginx tanpa satu flag port pun:

bash
$ docker run -d --network host --name web-host nginx

Output yang Dihasilkan:

text
8e4a7c2f9b3d1a5c7e9b0d2f4a6c8e0b2d4f6a1c3e5b7d9f0a2c4e6b8d0f2a4c
bash
$ curl -sI localhost:80

Output yang Dihasilkan:

text
HTTP/1.1 200 OK
Server: nginx/1.29.4
Date: Tue, 13 Oct 2026 18:47:22 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: bytes

Mari kita telaah demo yang tampak sederhana ini:

  1. Tidak ada -p sama sekali — perintahnya hanya --network host; pada mode bridge, tanpa -p container nginx tidak akan pernah terjangkau dari luar namespace-nya.
  2. Port 80 milik host yang terisi — nginx di dalam container membind port 80 pada namespace host, sehingga curl localhost:80 di mesin Budi langsung sampai ke container tanpa satu aturan DNAT pun bekerja.
  3. Header tetap nginx/1.29.4 — aplikasinya tetap container biasa; yang berubah hanyalah tempatnya menancapkan kabel jaringan.

Bukti Interface Host dari Dalam Container #

Klaim “container memakai interface host” mudah diuji: kita foto isi namespace jaringan dari dalam container dan membandingkannya dengan foto pada Chapter Bridge Network. Kali ini tidak ada eth0@if, dan satu-satunya alamat 172.17.x.x yang muncul adalah alamat docker0 sendiri — bukan alamat milik container:

bash
$ docker run --rm --network host alpine:3.20 ip addr

Output yang Dihasilkan:

text
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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP qlen 1000
    link/ether 3c:7a:8f:1d:24:b6 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.15/24 scope global eth0
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
    link/ether 02:42:8c:3a:17:d9 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever

Mari kita telaah tiga bukti yang tercetak di atas:

  1. eth0 adalah kartu LAN sungguhan host — alamatnya 192.168.1.15, alamat mesin Budi di jaringan rumah, dengan MAC 3c:7a:8f:1d:24:b6 milik kartu fisik; bandingkan dengan container bridge biasa yang melihat eth0@if15 beralamat 172.17.0.2 dengan MAC 02:42:... buatan Docker — dua dunia yang sepenuhnya berbeda untuk entitas bernama sama.
  2. docker0 ikut terlihat — bridge bawaan adalah interface di namespace host, dan karena container menumpang namespace itu, docker0 beserta alamat 172.17.0.1 ikut masuk ke daftar; dari dalam container mode host kita bisa menatap switch virtual itu secara langsung.
  3. Tidak ada @if di mana pun — akhiran @if15 pada container bridge adalah jejak veth pair, kabel dua ujung yang menghubungkan dua namespace; mode host tidak membuat kabel sama sekali karena memang tidak ada dua namespace yang perlu dijembatani.

Perhatikan pula status NO-CARRIER ... DOWN pada docker0: bridge tanpa satu pun container tercolok memang turun seperti switch tanpa penghuni — container web-host tidak menancap di sana karena tempatnya menancap adalah namespace host itu sendiri.

-p Dibuang Sama Sekali #

Apa yang terjadi bila kebiasaan lama kita ikut terbawa — menerbitkan port padahal container sudah di mode host? Docker menjawab dengan peringatan yang eksplisit:

bash
$ docker run --rm --network host -p 8080:80 alpine:3.20 echo hanya menguji peringatan

Output yang Dihasilkan:

text
WARNING: Published ports are discarded when using host network mode
hanya menguji peringatan

Peringatan Published ports are discarded bukan sekadar omongan sopan. Flag -p pada dasarnya adalah pesanan untuk membuat jembatan DNAT antara port host dan port container — dua sisi yang berada di dua namespace berbeda. Pada mode host kedua sisi itu menyatu menjadi satu, sehingga tidak ada dua sisi untuk dijembatani; port yang diiklankan identik dengan port yang dibind aplikasi, dan Docker pun membuang pesanan jembatan tersebut tanpa menjalankannya. Container tetap hidup dan berfungsi penuh — peringatan hanya memberi tahu bahwa flag yang kita tulis tidak berarti apa-apa.

Host versus Bridge #

Kedua mode kini sudah kita pegang dari dalam. Tabel berikut merangkum perbedaan mereka pada lima aspek yang paling sering menentukan pilihan:

AspekMode bridgeMode host
Network namespaceTerpisah untuk tiap containerDibagi dengan host — tidak dibuat baru
Cara membuka port-p 8080:80 lewat DNAT di hostAplikasi langsung mendengar port host
Ruang portMilik container sendiri — dua container boleh sama-sama memakai port 80Berbagi dengan seluruh proses host — bentrok port jadi nyata
Interface yang terlihat containerHanya lo dan eth0 veth privatSeluruh interface host, termasuk LAN dan docker0
Jalan ke internetLewat docker0 lalu NAT masqueradeLangsung lewat routing host, tanpa penerjemahan alamat

Kapan Memakai Host Network #

Tiga kelompok use case membuat mode ini layak dipertimbangkan. Pertama, agen pemantauan jaringan: perkakas yang tugasnya mengamati trafik host — menghitung paket, mengukur latensi antar interface — harus melihat interface host yang asli, sesuatu yang mustahil dari balik namespace terpisah. Kedua, proxy berkinerja tinggi: reverse proxy yang menerima seluruh trafik masuk kadang menanggalkan satu lapisan DNAT untuk menyederhanakan rantai hop, dengan gain yang jujur-jujur kecil namun nyata pada trafik sangat besar. Ketiga, aplikasi dengan port dinamis: server media atau protokol yang menegosiasikan port data secara mendadak saat runtime tidak bisa mendeklarasikan seluruh portnya di muka lewat -p — pada mode host setiap port yang dibuka langsung tersedia.

Sebelum lanjut, kita matikan lampu demo chapter ini:

bash
$ docker rm -f web-host

Output yang Dihasilkan:

text
web-host

Mode host melepas isolasi demi akses; pada ujung spektrum yang sebaliknya ada mode yang justru memperketat isolasi sampai ke nol konektivitas. Chapter None Network membedah mode --network none — namespace tanpa satu kabel pun, lengkap dengan pesan-pesan galatnya yang justru paling mendidik untuk dibaca.

Referensi #