Jaringan Docker dan port forwarding
Bagaimana container saling melihat, bagaimana publishing port berbeda dari EXPOSE sederhana, dan mengapa Docker melewati aturan ufw.
Diperbarui 23 Agustus 2026
Separuh masalah container berkaitan dengan jaringan: sebuah layanan tidak dapat menjangkau database, port sudah dipakai, panel tiba-tiba terbuka ke seluruh internet. Mari kita bedah cara kerjanya.
Tiga jenis jaringan
- bridge — default. Container mendapat alamat internal dan saling berkomunikasi; mereka keluar melalui NAT host.
- host — container menggunakan jaringan host secara langsung; publikasi port tidak diperlukan dan tidak berfungsi. Cepat, tetapi tanpa isolasi: port 80 container adalah port 80 host.
- none — tanpa jaringan sama sekali. Untuk tugas yang tidak membutuhkannya.
Jaringan kustom yang Anda buat atau dibuat oleh Compose berbeda dari bridge default dalam satu hal penting: resolusi nama berfungsi di dalamnya. Container app dapat menjangkau container db dengan nama db.
docker network create backend
docker network ls
docker network inspect backend
Di Compose, jaringan semacam itu dibuat secara otomatis untuk setiap proyek.
Publikasi port
ports:
- "127.0.0.1:8080:8080" # accessible only from the machine itself
- "80:80" # accessible to the whole internet
Di sebelah kiri adalah port pada host, di sebelah kanan adalah port di dalam container. Direktif EXPOSE pada image tidak mempublikasikan apa pun: itu hanya catatan tentang port mana yang didengarkan aplikasi.
Aturannya sederhana: publikasikan hanya yang harus dapat diakses dari luar. Database, panel, dan API internal dipasang pada 127.0.0.1, dan web server dengan sertifikat membukanya ke luar.
Docker menulis aturan
iptablessendiri dan melakukannya sebelum chain yang dikelola olehufw. Port yang dipublikasikan sebagai-p 8080:8080akan dapat diakses dari internet meskipunufwmenunjukkan “deny”. Jangan mengandalkan firewall — ikat port ke127.0.0.1.
Komunikasi antar container
services:
app:
networks: [frontend, backend]
db:
networks: [backend]
proxy:
networks: [frontend]
ports:
- "80:80"
- "443:443"
networks:
frontend:
backend:
Di sini database hanya dapat diakses oleh aplikasi, dan hanya web server yang menghadap ke luar. Ini adalah konfigurasi yang tepat untuk stack apa pun.
Di dalam container, rujuk container tetangga dengan nama layanannya: postgres://db:5432/app. Alamat localhost di dalam container berarti container itu sendiri, bukan host — kesalahan paling umum kedua setelah latest.
Untuk menjangkau layanan yang berjalan di host itu sendiri dari container, gunakan nama host.docker.internal dengan menambahkan:
extra_hosts:
- "host.docker.internal:host-gateway"
Diagnostik
docker compose exec app ping -c2 db
docker compose exec app getent hosts db
sudo ss -tulpn | grep LISTEN
docker port <container>
ss akan menunjukkan antarmuka mana yang sebenarnya didengarkan oleh suatu port: 0.0.0.0:8080 — terbuka ke luar, 127.0.0.1:8080 — tidak.
Kesalahan umum
- “Port already in use”. Port tersebut dipakai oleh container lain atau layanan host.
sudo ss -tulpn | grep :80akan menemukan penyebabnya. - Container di proyek Compose yang berbeda tidak dapat saling melihat. Setiap proyek memiliki jaringannya sendiri. Hubungkan secara eksplisit melalui
networks: { shared: { external: true } }. - Aplikasi mendengarkan pada
127.0.0.1di dalam container. Maka publikasi tidak akan membantu: Anda tidak dapat menjangkaunya dari luar container. Konfigurasikan aplikasi untuk mendengarkan pada0.0.0.0. - Bandwidth. Hingga 500 Mbps dibagi per host. Distribusi file membaginya dengan semua hal lain.