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 flag | Pemetaan yang lahir |
|---|---|
-p 8080:80 | port host 8080 di semua antarmuka menuju port container 80 |
-p 127.0.0.1:8081:80 | hanya localhost host yang bisa menghubungi |
-p 8083:80/udp | pemetaan protokol udp, terpisah dari ruang nomor tcp |
Kita nyalakan container percobaan dengan bentuk paling kanonik:
$ docker run -d --name web -p 8080:80 nginxOutput yang Dihasilkan:
f7c2a91b3e55913c4a5f1c6c0a4d8e2b3f4a5b6c7d8e9f0a1b2c3d4e5f60718aInventaris pemetaan container itu dibaca dengan satu perintah:
$ docker port webOutput yang Dihasilkan:
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080Mari kita telaah format kedua baris itu:
- Sisi kiri
80/tcpadalah port container — nomor port dan protokol di dalam jaringan privat; arah membaca selalu dari kiri ke kanan. - Sisi kanan
0.0.0.0:8080adalah pintu host — alamat antarmuka dan port di sisi host. Tanpa segmen alamat pada flag, daemon mengikat pemetaan ke0.0.0.0(seluruh antarmuka IPv4) sekaligus[::](seluruh antarmuka IPv6) — itulah mengapa kedua baris muncul berpasangan. docker port web 80memfilter 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:
$ docker psOutput yang Dihasilkan:
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 webKolom 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:
$ curl -sI http://localhost:8080Output yang Dihasilkan:
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: bytesFlag -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:
$ curl -sI http://192.168.1.15:8080Output yang Dihasilkan:
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: bytesKeluarannya 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:
$ docker run -d --name web-lokal -p 127.0.0.1:8081:80 nginxOutput yang Dihasilkan:
e4b9a2c7f5d31860b1a4c9e2f7b5d8c3a1e6f4b9d2c7a5e8f1b4d6c3a9e2f5b8d1c$ docker port web-lokalOutput yang Dihasilkan:
80/tcp -> 127.0.0.1:8081Satu 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:
$ docker run -d --name web2 -p 8080:80 nginxOutput yang Dihasilkan:
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:
$ ss -tlnp | grep 8080Output yang Dihasilkan:
LISTEN 0 4096 0.0.0.0:8080 0.0.0.0:* users:(("docker-proxy",pid=3182,fd=7))Mari kita telaah hasil diagnosisnya:
- Kolom
users:menunjukdocker-proxy— proses pembantu daemon yang memegang port; pemegangnya adalah container Docker, dandocker psbeserta kolomPORTSakan menunjuk containerwebkita. - Nama proses biasa seperti
apache2ataunodeberarti 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. - 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:
$ docker rm web2
$ docker run -d --name web2 -p 8082:80 nginxOutput yang Dihasilkan:
web2
2b8f5e1c9a7d4360f1e8c5b2a9d6f3e7c1b4a8d5f2c9e6b1a4d7f3c5e8b2a6d9f1cUji 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:
$ docker run -d --name web-udp -p 8083:80/udp nginxOutput yang Dihasilkan:
9c3f7b1e5a9d2460c8e2f5b7a1d4c9e6f3b8a5d2c7f1e4b9a6d3c5f8e2b7a1d4c9f$ docker port web-udpOutput yang Dihasilkan:
80/udp -> 0.0.0.0:8083
80/udp -> [::]:8083Pemetaan 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:
| Gejala | Perintah diagnosis | Artinya |
|---|---|---|
curl localhost:8080 menjawab Connection refused | docker port web | pemetaan tidak ada, salah port, atau container tidak berjalan |
docker run gagal Bind ... port is already allocated | ss -tlnp | grep 8080 | port host dipegang container lain lewat docker-proxy, atau proses host |
| Dari mesin lain tak terjangkau, dari host sendiri normal | docker port web | pemetaan terikat ke 127.0.0.1 saja |
docker port web kosong sama sekali | docker ps lalu periksa perintah run | tidak ada flag -p; EXPOSE hanyalah metadata, bukan penerbitan |
| Klien udp tidak menerima jawaban | docker port web 80/udp | pemetaan udp ada, tetapi aplikasi tidak mendengarkan udp |
Kita bereskan seluruh container percobaan:
$ docker rm -f web web-lokal web2 web-udpOutput yang Dihasilkan:
web
web-lokal
web2
web-udpPintu 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 #
- docker container port — CLI Reference — membaca pemetaan port container berjalan beserta filter portnya.
- docker container run — CLI Reference
— flag
-pdan bentuk segmen alamat, port, serta protokol. - Docker Networking Overview — bagaimana pemetaan port diteruskan ke jaringan container.