Publishing vs Exposing

Siapa yang dapat menjangkau container: host dan luar jaringan, sesama container, atau keduanya.

Daftar isi

Topik ini memisahkan dua kata kerja yang sering tertukar pada pembahasan jaringan Docker. Publishing adalah pemetaan port container ke port host, komputer tempat Docker berjalan, sedangkan exposing hanya menandai port yang dilayani container. Keduanya menentukan siapa yang dapat menjangkau sebuah container, mulai dari dunia luar, sesama container, hingga host itu sendiri. Setelah membacanya, pemilihan opsi yang tepat untuk setiap audiens memiliki dasar yang jelas.

Publishing, pemetaan port ke host#

Publishing membuat port di dalam container dapat dijangkau dari luar host. Opsi -p pada docker run memerintahkan Docker membuat aturan penerusan pada host, sehingga lalu lintas yang tiba di port host diteruskan ke port di dalam container. Nilai -p 8000:8000 memasangkan port 8000 pada host dengan port 8000 di dalam container, sedangkan port tambahan diteruskan dengan mengulang opsi tersebut untuk setiap pasangan berikutnya. Karena itu, satu container yang melayani aplikasi dan antarmuka administrasi dapat membawa dua publikasi sekaligus.

bash
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# aplikasi catatan dengan port 8000 yang dipublikasikan
docker run -d --name catatan-web -p 8000:8000 catatan

Publikasi tidak berhenti pada pemetaan port. Docker menambahkan aturan firewall, yaitu aturan penyaringan lalu lintas jaringan pada host, agar port yang dipublikasikan menerima lalu lintas dari luar, termasuk dari antarmuka yang mengarah ke jaringan publik. Akibatnya, container yang dipublikasikan tanpa pengikatan alamat dapat dijangkau komputer lain pada jaringan tersebut, sehingga keberadaan aturan ini perlu diperhitungkan pada host yang terbuka ke internet.

Exposing, penandaan port container#

Exposing hanya menandai port yang dilayani container tanpa memetakan apa pun. Penanda tersebut berupa daftar port pada metadata image, yaitu kumpulan informasi yang menjelaskan image. Daftar itu ditulis melalui instruksi EXPOSE pada Dockerfile dan berfungsi sebagai dokumentasi niat bagi pembaca image. Container yang menandai port tanpa mempublikasikannya tetap tidak terjangkau dari luar host, karena penandaan tidak membuat aturan penerusan apa pun.

Pada komunikasi antar container, penandaan ini justru tidak dibutuhkan. Sesama container yang menjadi anggota jaringan yang sama dapat menjangkau semua port satu sama lain secara langsung, termasuk port yang tidak ditandai dan tidak dipublikasikan, cukup dengan menyebut nama container dan portnya. Inilah alasan basis data PostgreSQL pada jaringan kustom dapat dihubungi di port 5432 tanpa pernah dipublikasikan ke host. Tabel berikut merangkum tiga audiens beserta syarat aksesnya.

AudiensYang dapat dijangkauSyaratnya
Dunia luar hostHanya port yang dipublikasikan dengan -pPublikasi port saat docker run
Sesama container pada jaringan yang samaSemua port container, tanpa pengecualianKedua container menjadi anggota jaringan yang sama
Host itu sendiriAlamat container pada jembatan, dan localhost setelah port dipublikasikanContainer berjalan, publikasi untuk jalur localhost

Baris pertama dan kedua tabel menunjukkan bahwa -p melayani audiens dari luar host, sedangkan komunikasi internal tidak memerlukannya sama sekali. Aplikasi catatan yang dipublikasikan pada port 8000 tetap menghubungi basis datanya melalui nama db dan port 5432 dari dalam jaringan, bukan melalui port host. Mencampur kedua jalur tersebut, misalnya menghubungi basis data melalui port host yang dipublikasikan, menambah permukaan serangan tanpa keuntungan apa pun.

Mengikat publikasi ke loopback#

Bentuk -p host:container mengikat port host ke seluruh antarmuka secara default. Bentuk -p 127.0.0.1:8000:8000 menambahkan alamat di depan dan membuat publikasi terikat (bind) hanya ke antarmuka loopback, yaitu antarmuka yang hanya dapat dijangkau dari mesin itu sendiri. Browser pada host tetap dapat membuka localhost:8000, sedangkan komputer lain pada jaringan yang sama tidak melihat port tersebut sama sekali.

Perbedaan kedua bentuk pengikatan ini dapat diperagakan tanpa Docker. Server uji berikut dijalankan dengan pengikatan ke loopback, kemudian keterjangkauannya diuji dari localhost dan dari alamat antarmuka eth0 milik mesin lingkungan uji.

bash
# alamat antarmuka eth0 pada mesin lingkungan uji
IP_ETH0=$(hostname -I | awk '{print $1}')
# server uji yang terikat hanya ke antarmuka loopback
python3 -m http.server 8090 --bind 127.0.0.1 >/dev/null 2>&1 &
PID_SERVER=$!
# beri waktu server siap menerima koneksi
sleep 1
# uji keterjangkauan dari localhost
curl -s -o /dev/null -w "via localhost: %{http_code}\n" http://127.0.0.1:8090/
# uji keterjangkauan dari alamat eth0
if curl -s -o /dev/null --connect-timeout 2 "http://$IP_ETH0:8090/"; then
  echo "via eth0: terjangkau"
else
  echo "via eth0: tidak terjangkau"
fi
# hentikan server uji
kill $PID_SERVER
text Keluaran
via localhost: 200
via eth0: tidak terjangkau

Keluaran menunjukkan bahwa permintaan dari localhost diterima dengan kode status 200, sedangkan permintaan melalui alamat eth0 tidak pernah sampai, karena tidak ada proses yang mendengarkan pada alamat tersebut. Pada Docker, peran server uji ini diambil oleh aturan publikasi port, dan bentuk -p 127.0.0.1:8000:8000 menghasilkan perilaku yang persis sama. Koneksi dari host tetap diterima, sedangkan koneksi dari komputer lain berhenti di host tanpa pernah mencapai container.

Pola pengikatan loopback lazim digunakan untuk layanan administrasi, antarmuka pemantauan, dan basis data yang hanya perlu dijangkau alat di host. Aturan firewall yang ditambahkan Docker mengikuti pengikatan tersebut, sehingga port yang terikat loopback tidak dibuka ke luar. Pada host produksi yang terhubung langsung ke internet, mengikat setiap publikasi yang tidak memang harus terbuka merupakan kebiasaan yang aman.

Ringkasan#

  • Publishing memetakan port container ke port host melalui -p dan menjadi satu-satunya jalur bagi audiens di luar host.
  • Exposing hanya menandai port pada metadata image dan tidak membuka akses apa pun.
  • Sesama container pada jaringan yang sama saling menjangkau seluruh port melalui nama container, tanpa -p maupun EXPOSE.
  • Bentuk -p 127.0.0.1:port:port mengikat publikasi ke loopback, sehingga port hanya terjangkau dari host itu sendiri.

Referensi#