September 27, 2026

Docker Network.

Dasar networking Docker: driver bridge/host/none, DNS di user-defined bridge, network di Compose, beda expose vs publish port, dan cara menghubungkan container antar project Compose.

Hampir semua error β€œcontainer A tidak bisa konek ke container B” berakar dari salah paham soal network Docker. Catatan ini merangkum konsep yang perlu dipahami: jenis driver, DNS antar container, network di Compose, dan beda expose vs publish port.


1. Driver Network

docker network ls
# NETWORK ID     NAME      DRIVER    SCOPE
# 1a2b3c...      bridge    bridge    local
# 4d5e6f...      host      host      local
# 7a8b9c...      none      null      local
DriverPerilakuKapan dipakai
bridgeNetwork privat virtual di host; container dapat IP internal (mis. 172.17.0.x)Default, hampir selalu ini
hostContainer memakai network stack host langsung, tanpa isolasiPerforma jaringan maksimal, tool monitoring. Di Linux penuh; di Docker Desktop perlu diaktifkan dan perilakunya terbatas
noneTanpa network sama sekali (hanya loopback)Job batch yang tidak boleh akses jaringan
overlayNetwork lintas beberapa hostDocker Swarm
macvlan / ipvlanContainer tampil sebagai perangkat di LAN fisikKasus khusus (home lab , perangkat jaringan)
docker run --rm --network host nginx          # nginx langsung di port 80 host
docker run --rm --network none alpine ip addr # hanya lo

2. Default Bridge vs User-Defined Bridge

Ini poin terpenting. Container yang dijalankan tanpa --network masuk ke network bawaan bernama bridge, dan di sana tidak ada DNS berdasarkan nama container.

Default bridgeUser-defined bridge
Resolusi nama container (ping db)Tidak bisa (hanya IP)Bisa, via DNS internal Docker
IsolasiSemua container β€œliar” bercampurHanya container yang di-join
Connect/disconnect saat jalanTerbatasBisa, docker network connect
RekomendasiHindari untuk aplikasiGunakan ini

Contoh:

docker network create appnet

docker run -d --name db --network appnet \
  -e POSTGRES_PASSWORD=secret postgres:17

docker run --rm --network appnet postgres:17 \
  pg_isready -h db -U postgres
# db:5432 - accepting connections

db di-resolve oleh DNS server internal Docker (127.0.0.11 di dalam container). Kamu juga bisa menambah nama lain lewat --network-alias.


3. Expose vs Publish Port

Dua hal yang sering tertukar:

EXPOSE 3000 (Dockerfile) / expose: (Compose)-p 8080:3000 / ports:
FungsiDokumentasi port yang didengarkan aplikasiMembuka port container ke host
Bisa diakses dari host/browser?TidakYa, di localhost:8080
Dibutuhkan untuk komunikasi antar container di network yang sama?TidakTidak

Artinya: antar container di network yang sama, semua port sudah bisa dijangkau memakai port asli container (misal mysql:3306), tanpa ports: sama sekali. ports: hanya untuk akses dari luar (browser, GUI database di laptop).

Format publish:

-p 8080:80              # host 8080 β†’ container 80, di semua interface (0.0.0.0)
-p 127.0.0.1:8080:80    # hanya bisa diakses dari mesin ini
-p 5353:53/udp          # UDP
-P                      # publish semua port EXPOSE ke port acak di host

Keamanan: di server Linux, port yang dipublish Docker melewati aturan UFW karena Docker menulis aturan iptables sendiri. Untuk database, bind ke 127.0.0.1: atau jangan publish sama sekali.


4. Network di Docker Compose

Compose otomatis membuat satu network <project>_default, dan setiap service bisa saling panggil memakai nama service:

services:
  app:
    build: .
    environment:
      DB_HOST: mysql      # nama service = hostname
  mysql:
    image: mysql:8.4

Kamu bisa membuat beberapa network untuk memisahkan tier:

services:
  proxy:
    image: nginx:alpine
    ports: ["80:80"]
    networks: [frontend]

  app:
    build: .
    networks: [frontend, backend]

  mysql:
    image: mysql:8.4
    networks: [backend]     # proxy tidak bisa menjangkau mysql

networks:
  frontend:
  backend:
    internal: true          # tanpa akses keluar ke internet

5. Menghubungkan Container Antar Project Compose

Kasus umum: satu reverse proxy (Nginx Proxy Manager, Traefik, Caddy) melayani beberapa project Compose yang terpisah. Caranya dengan external network yang dipakai bersama.

Buat network sekali:

docker network create proxy

Project reverse proxy:

# ~/proxy/compose.yaml
services:
  caddy:
    image: caddy:2
    ports: ["80:80", "443:443"]
    networks: [proxy]

networks:
  proxy:
    external: true

Project aplikasi:

# ~/blog/compose.yaml
services:
  blog:
    image: ghost:5
    networks: [default, proxy]   # tetap di default untuk konek ke DB-nya sendiri
  blog-db:
    image: mysql:8.4
    # hanya di network default β†’ tidak terlihat dari project lain

networks:
  proxy:
    external: true

Sekarang Caddy bisa reverse_proxy blog:2368. Tips: beri nama service yang unik antar project (blog, bukan app) supaya DNS tidak ambigu di network bersama.

Alternatif cepat untuk container yang sudah jalan:

docker network connect proxy blog-blog-1
docker network disconnect proxy blog-blog-1

Pola serupa cocok untuk home lab seperti Home Server , dengan Cloudflare Tunnel sebagai pintu masuk dari internet.


6. Mengakses Host dari Container

Kadang container perlu konek ke service yang jalan di laptop (misal MySQL lokal):

# Docker Desktop (macOS/Windows): sudah tersedia
mysql -h host.docker.internal

# Linux: tambahkan manual
docker run --add-host=host.docker.internal:host-gateway ...
services:
  app:
    extra_hosts:
      - "host.docker.internal:host-gateway"

Jangan pakai localhost β€” di dalam container, localhost adalah container itu sendiri.


7. Debugging

docker network inspect appnet                 # daftar container & IP
docker inspect -f '{{json .NetworkSettings.Networks}}' db | jq
docker run --rm -it --network appnet nicolaka/netshoot   # toolbox: dig, curl, nc, tcpdump
# di dalam netshoot:
dig db
nc -zv db 5432
curl -I http://app:8000

8. Pitfalls

  • localhost / 127.0.0.1 di connection string β†’ mengarah ke container sendiri. Pakai nama service.
  • Memakai port host di antar container (mysql:3307) β†’ salah; pakai port container (mysql:3306).
  • Container di default bridge tidak bisa saling panggil dengan nama β†’ buat user-defined network.
  • Aplikasi listen di 127.0.0.1 di dalam container β†’ tidak bisa diakses meski port dipublish. Harus 0.0.0.0 (contoh: php artisan serve --host=0.0.0.0, vite --host).
  • Publish database ke 0.0.0.0 di VPS β†’ terbuka ke internet walau UFW aktif.
  • Subnet bentrok dengan VPN/LAN kantor (172.17.0.0/16) β†’ atur default-address-pools di /etc/docker/daemon.json.

Lanjutan: Docker Compose untuk Dev Environment , Docker Volume .

Referensi: Networking overview , Bridge network driver , Networking in Compose .

Hey! I’m Fanny, the software engineer tending to this digital garden. You can read more about me, or subscribe by email.

Comments