Docker Networking — DevOps

Network di Docker Docker membuat jaringan virtual sehingga container bisa berkomunikasi satu sama lain. Memahami networking Docker sangat penting untuk…

Docker memberi container-container-mu jaringan virtual sendiri: tiap container dapat IP sendiri, nama yang bisa dipanggil container lain, dan localhost miliknya sendiri. Dari luar, container cuma bisa dicapai lewat port yang sengaja kamu buka. Bayangin gedung kantor. Tiap ruangan punya nomor extension telepon. Di gedung baru ada resepsionis: sebut nama ruangannya, kamu langsung disambungkan. Menelepon "nomor sendiri" dari sebuah ruangan cuma menyambung ke ruangan itu. Dan dari jalan, orang cuma bisa menelepon ruangan yang punya saluran langsung ke luar.

🧪 Tebakan cepat: di dalam container app, DATABASE_URL masih postgres://catatan:...@localhost:5432/catatan, seperti waktu catatan-api jalan langsung di web-1. Postgres sekarang jalan di container db. Apakah app-nya tersambung? Tebak dulu, jawabannya ada di bagian "localhost di dalam container".

Network bridge: tiap container punya IP sendiri

Network driver menentukan cara container terhubung. Yang paling sering dipakai bridge, dan itu juga default-nya: container di satu host disambungkan lewat switch virtual. Driver lain: host (container memakai jaringan host langsung, tanpa isolasi port), none (tanpa jaringan sama sekali), dan overlay (menyambung container di banyak host, untuk Docker Swarm).

Ada dua macam bridge:

Default bridge Bridge buatanmu
Cara dapat container tanpa --network docker network create catatan-net
Contoh subnet 172.17.0.0/16 172.18.0.0/16
Panggil container lewat nama gak bisa bisa

Memanggil container lewat nama

Di bridge buatanmu, Docker menjalankan DNS sendiri: nama container (atau nama service di Compose) otomatis jadi nama host.

$ docker network create catatan-net
$ docker run -d --name db --network catatan-net \
    -e POSTGRES_USER=catatan -e POSTGRES_PASSWORD=$DB_PASSWORD \
    -v db-data:/var/lib/postgresql/data postgres:16
$ docker run -d --name catatan-api --network catatan-net \
    -e DATABASE_URL=postgres://catatan:$DB_PASSWORD@db:5432/catatan \
    -p 127.0.0.1:8080:3000 ghcr.io/budi/catatan-api:a41c9e2
$ docker logs catatan-api
Server jalan di http://localhost:3000

Docker Compose membuat bridge buatan otomatis untuk tiap project (catatan-api_default), jadi di Compose, nama service dipakai sebagai hostname: db:5432, redis:6379. Itu sebabnya file Compose di lesson sebelumnya bisa menulis @db:5432 begitu saja.

localhost di dalam container

localhost (127.0.0.1) di dalam container berarti container itu sendiri, bukan web-1 dan bukan container lain. Di container app gak ada Postgres, jadi koneksinya ditolak:

Gagal konek ke database: connect ECONNREFUSED 127.0.0.1:5432

Jadi gak, app-nya gak tersambung. Itu jawaban tebakannya. Ganti host-nya dengan nama container atau service: postgres://catatan:...@db:5432/catatan. Kalau container justru perlu memanggil program yang jalan langsung di host, Docker Desktop menyediakan nama host.docker.internal; di Linux, tambahkan --add-host=host.docker.internal:host-gateway.

Port: dipublikasikan atau cuma dicatat

Container di bridge gak bisa dicapai dari luar host sampai port-nya dipublikasikan dengan -p:

Opsi Bisa dibuka dari Tampil di docker ps
(tanpa -p, cuma EXPOSE 3000) container lain di network yang sama 3000/tcp
-p 8080:3000 web-1 dan seluruh internet 0.0.0.0:8080->3000/tcp
-p 127.0.0.1:8080:3000 web-1 saja 127.0.0.1:8080->3000/tcp

Latihan lesson ini mengurai teks opsi -p itu: "8080:3000" jadi { host: "0.0.0.0", hostPort: 8080, containerPort: 3000 }, dan "127.0.0.1:3000:3000" jadi { host: "127.0.0.1", hostPort: 3000, containerPort: 3000 }. Potong di :; dua bagian berarti IP-nya default 0.0.0.0, tiga bagian berarti bagian pertama IP-nya. Port-nya angka, jadi ubah dengan Number(...).

⚠️ Jebakan yang sering ketemu

TL;DR: Network driver default Docker adalah bridge. Di bridge buatanmu (docker network create) dan di network yang dibuat Compose, Docker punya DNS sendiri, jadi container saling memanggil lewat nama (db:5432); di default bridge, nama gak bisa dipakai. localhost di dalam container berarti container itu sendiri, bukan host dan bukan container lain. EXPOSE cuma mencatat port; -p HOST:CONTAINER (-p 8080:3000) yang meneruskan port host ke container, di 0.0.0.0 (semua alamat, termasuk internet) kecuali kamu menulis IP di depannya (-p 127.0.0.1:8080:3000). Antar container di network yang sama gak perlu -p, dan database di server jangan dipublikasikan ke 0.0.0.0.

Yang akan kamu pelajari