Chapter sebelumnya ditutup di ambang sebuah pintu: sepanjang studi kasus net-latihan, seluruh percakapan berlangsung di jaringan privat dan dunia luar memang tidak diizinkan masuk. Sekarang saatnya pintu itu kita buka — daemon mendengarkan port tertentu di host, lalu meneruskan seluruh lalu lintas yang masuk ke port di dalam container. Anatomi flag -p lengkap dengan segmen alamat, rentang, dan protokolnya sudah kita kuasai pada Chapter Port Publishing di Section Konfigurasi Container, jadi chapter ini sengaja tidak mengulangnya; fokus kita bergeser ke dua keterampilan yang justru jarang diajarkan: memverifikasi bahwa pemetaan benar-benar bekerja dari ujung ke ujung, dan membaca resep diagnosis ketika pintu itu macet. Kedua keterampilan ini menutup satu kesenjangan nyata — pemetaan port yang salah hampir selalu terlihat benar sampai ada yang mencoba menghubunginya.

Menyalakan Pintu dan Membacanya #

Rekap singkat tiga bentuk -p yang paling sering dipakai — bedah lengkapnya tetap di Chapter Port Publishing:

Bentuk flagPemetaan yang lahir
-p 8080:80port host 8080 di semua antarmuka menuju port container 80
-p 127.0.0.1:8081:80hanya localhost host yang bisa menghubungi
-p 8083:80/udppemetaan protokol udp, terpisah dari ruang nomor tcp

Kita nyalakan container percobaan dengan bentuk paling kanonik:

bash
$ docker run -d --name web -p 8080:80 nginx

Output yang Dihasilkan:

text
f7c2a91b3e55913c4a5f1c6c0a4d8e2b3f4a5b6c7d8e9f0a1b2c3d4e5f60718a

Inventaris pemetaan container itu dibaca dengan satu perintah:

bash
$ docker port web

Output yang Dihasilkan:

text
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080

Mari kita telaah format kedua baris itu:

  1. Sisi kiri 80/tcp adalah port container — nomor port dan protokol di dalam jaringan privat; arah membaca selalu dari kiri ke kanan.
  2. Sisi kanan 0.0.0.0:8080 adalah pintu host — alamat antarmuka dan port di sisi host. Tanpa segmen alamat pada flag, daemon mengikat pemetaan ke 0.0.0.0 (seluruh antarmuka IPv4) sekaligus [::] (seluruh antarmuka IPv6) — itulah mengapa kedua baris muncul berpasangan.
  3. docker port web 80 memfilter keluaran hanya untuk port container 80 — berguna saat container menerbitkan banyak pintu sekaligus dan kita hanya curiga pada satu.

Informasi yang sama juga selalu tampak pada kolom PORTS di docker ps:

bash
$ docker ps

Output yang Dihasilkan:

text
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
f7c2a91b3e55   nginx     "/docker-entrypoint.…"   30 seconds ago  Up 29 seconds  0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   web

Kolom 0.0.0.0:8080->80/tcp itu perlu kita pecah per segmen agar terbaca seperti kalimat: 0.0.0.0 adalah alamat host yang diikat, 8080 adalah port host tempat dunia luar mengetuk, ->80 menunjuk port container tujuan, dan akhiran /tcp mencatat protokolnya. Dua belas karakter pertama CONTAINER ID juga cocok dengan awalan ID panjang yang tercetak saat docker run — jembatan identitas yang kita kenal sejak Section Docker Image.

Verifikasi Ujung ke Ujung #

Pemetaan baru boleh disebut bekerja setelah permintaan sungguhan menembusnya. Dari mesin host:

bash
$ curl -sI http://localhost:8080

Output yang Dihasilkan:

text
HTTP/1.1 200 OK
Server: nginx/1.29.4
Date: Tue, 13 Oct 2026 20:31:47 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 17 Sep 2026 14:26:11 GMT
Connection: keep-alive
ETag: "6aabf883-267"
Accept-Ranges: bytes

Flag -I meminta hanya header respons — cukup untuk membuktikan layanan hidup tanpa memuat halaman. Baris HTTP/1.1 200 OK bersama Server: nginx/1.29.4 menyatakan rantai lengkap bekerja: curl menuju port 8080 di host, aturan penerusan daemon membawa koneksi ke port 80 milik container, dan nginx menjawab. Karena pemetaan terikat ke 0.0.0.0, pintu ini juga terbuka bagi mesin lain di jaringan lokal. Siti membuktikannya dari laptopnya di seberang meja:

bash
$ curl -sI http://192.168.1.15:8080

Output yang Dihasilkan:

text
HTTP/1.1 200 OK
Server: nginx/1.29.4
Date: Tue, 13 Oct 2026 20:34:12 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 17 Sep 2026 14:26:11 GMT
Connection: keep-alive
ETag: "6aabf883-267"
Accept-Ranges: bytes

Keluarannya identik selain stempel Date yang mundur beberapa menit — permintaan dari mesin Siti menempuh jalur yang sama: LAN, alamat host Budi 192.168.1.15, port 8080, container. Verifikasi dari dua arah seperti inilah yang layak dilakukan setiap kali kita membuka pintu baru.

Mengikat Hanya ke Localhost #

Bentuk kedua membatasi pintu host ke antarmuka loopback. Kita jalankan varian berikut di port host 8081:

bash
$ docker run -d --name web-lokal -p 127.0.0.1:8081:80 nginx

Output yang Dihasilkan:

text
e4b9a2c7f5d31860b1a4c9e2f7b5d8c3a1e6f4b9d2c7a5e8f1b4d6c3a9e2f5b8d1c
bash
$ docker port web-lokal

Output yang Dihasilkan:

text
80/tcp -> 127.0.0.1:8081

Satu baris saja — tanpa pasangan IPv6, karena pemetaan hanya hidup di 127.0.0.1. curl -sI http://localhost:8081 dari host Budi tetap menjawab 200 OK, sementara percobaan yang sama dari laptop Siti kini ditolak: curl: (7) Failed to connect to 192.168.1.15 port 8081. Pola ini adalah rumah yang tepat bagi layanan internal: database development yang ingin dijangkau alat SQL di laptop sendiri cukup diterbitkan sebagai -p 127.0.0.1:5433:5432 — sesama container tetap menghubunginya lewat nama dan port 5432 di dalam jaringan, tanpa satu pintu pun terbuka ke LAN.

Debug: Port Sudah Dipakai #

Kegagalan paling sering menyapa saat mencoba menempati pintu host yang sudah diduduki. Budi menjalankan container kedua pada port yang sama:

bash
$ docker run -d --name web2 -p 8080:80 nginx

Output yang Dihasilkan:

text
docker: Error response from daemon: driver failed programming external connectivity on endpoint web2 (7e5c3a9f2b8d41760c2a5f8e1b7d3c9a4f2e8b5d7c1a4f9e2b8d5c3a6f1e4b7d2c): Bind for 0.0.0.0:8080 failed: port is already allocated
See 'docker run --help'.

Diagnosis satu baris dari sisi host:

bash
$ ss -tlnp | grep 8080

Output yang Dihasilkan:

text
LISTEN 0   4096   0.0.0.0:8080   0.0.0.0:*   users:(("docker-proxy",pid=3182,fd=7))

Mari kita telaah hasil diagnosisnya:

  1. Kolom users: menunjuk docker-proxy — proses pembantu daemon yang memegang port; pemegangnya adalah container Docker, dan docker ps beserta kolom PORTS akan menunjuk container web kita.
  2. Nama proses biasa seperti apache2 atau node berarti pemegangnya layanan host — web server native atau aplikasi development yang menyala langsung di mesin, di luar kendali Docker; kasus ini kita bedah penuh pada Chapter Troubleshooting Network.
  3. Solusi tercepat adalah menggeser nomor port host — hentikan pemegang lama bila memang boleh dimatikan, atau pindahkan container baru ke pintu lain. Dua pemetaan juga boleh berbagi satu nomor port asalkan mengikat ke alamat IP yang berbeda.

Container web2 yang gagal tetap tercipta berstatus Created — sisa yang harus dibuang sebelum nama itu terpakai lagi, kebiasaan yang kita bentuk sejak Chapter Port Publishing:

bash
$ docker rm web2
$ docker run -d --name web2 -p 8082:80 nginx

Output yang Dihasilkan:

text
web2
2b8f5e1c9a7d4360f1e8c5b2a9d6f3e7c1b4a8d5f2c9e6b1a4d7f3c5e8b2a6d9f1c

Uji Pemetaan udp Singkat #

Ruang nomor port udp terpisah dari tcp, dan pemetaan udp punya kewajiban tambahan: aplikasi di dalam container harus benar-benar mendengarkan udp. Kita buktikan keduanya sekaligus:

bash
$ docker run -d --name web-udp -p 8083:80/udp nginx

Output yang Dihasilkan:

text
9c3f7b1e5a9d2460c8e2f5b7a1d4c9e6f3b8a5d2c7f1e4b9a6d3c5f8e2b7a1d4c9f
bash
$ docker port web-udp

Output yang Dihasilkan:

text
80/udp -> 0.0.0.0:8083
80/udp -> [::]:8083

Pemetaan udp berdiri dengan sah — tetapi nginx hanya mendengarkan tcp, sehingga klien udp yang mengetuk pintu 8083 tidak akan pernah dijawab. Kasus penggunaan aslinya justru sebaliknya: layanan berbasis udp seperti DNS pada port 53 diterbitkan dengan -p 5353:53/udp, dan pemetaan tcp-nya tidak diperlukan sama sekali. Pemetaan hanya membuka jalan; protokol yang bicara tetap milik aplikasi.

Resep Diagnosis Pemetaan #

Lima gejala yang paling sering muncul di sekitar pemetaan port, beserta perintah dan maknanya:

GejalaPerintah diagnosisArtinya
curl localhost:8080 menjawab Connection refuseddocker port webpemetaan tidak ada, salah port, atau container tidak berjalan
docker run gagal Bind ... port is already allocatedss -tlnp | grep 8080port host dipegang container lain lewat docker-proxy, atau proses host
Dari mesin lain tak terjangkau, dari host sendiri normaldocker port webpemetaan terikat ke 127.0.0.1 saja
docker port web kosong sama sekalidocker ps lalu periksa perintah runtidak ada flag -p; EXPOSE hanyalah metadata, bukan penerbitan
Klien udp tidak menerima jawabandocker port web 80/udppemetaan udp ada, tetapi aplikasi tidak mendengarkan udp

Kita bereskan seluruh container percobaan:

bash
$ docker rm -f web web-lokal web2 web-udp

Output yang Dihasilkan:

text
web
web-lokal
web2
web-udp

Pintu host kini terpetakan utuh: dinyalakan, dibaca, diverifikasi dari dua arah, dibatasi ke localhost, dan didiagnosis ketika macet. Namun perhatikan satu batas yang tetap berdiri sepanjang chapter ini: satu container hanya pernah dikenal dengan satu nama web di jaringannya. Docker sebenarnya mengizinkan sebuah container menyandang nama-nama tambahan yang kita tentukan sendiri — dan di balik kemampuan itu menunggu pola arsitektur yang menarik: round-robin DNS, blue-green lokal, sampai mock service untuk pengembangan. Flag --network-alias membuka semuanya pada chapter berikutnya.

Referensi #