Bridge Network #
Di antara semua network driver yang tersedia di Docker, bridge adalah yang paling sering kamu temui — bahkan mungkin tanpa kamu sadari. Setiap kali kamu menjalankan docker run tanpa argumen --network, container otomatis masuk ke default bridge. Di balik kesederhanaan perintah itu, ada arsitektur yang elegan: virtual switch, veth pair, IPAM, dan iptables NAT yang bekerja sama untuk memberikan container akses jaringan yang terisolasi tapi fungsional.
Bridge adalah pondasi yang harus kamu pahami sebelum melompat ke driver lain (host, overlay, macvlan). Setelah paham bridge, semua driver lain terasa seperti variasi dari konsep yang sama — hanya berbeda di tingkat isolasi dan cakupan.
Artikel ini membahas bridge secara mendalam: cara kerjanya di level OS, perbedaan default bridge dengan user-defined bridge, kenapa yang satu jauh lebih direkomendasikan, dan bagaimana bridge berinteraksi dengan NAT, port mapping, dan DNS. Pada akhirnya kamu akan bisa merancang topologi network multi-container yang aman dan scalable.
Apa Itu Bridge Network? #
Bridge network di Docker adalah virtual switch layer-2 yang berjalan di dalam host. Switch ini menghubungkan banyak container sekaligus dan meneruskan paket Ethernet di antara mereka. Secara konseptual, bridge = virtual network switch, dan container = perangkat yang tercolok ke switch itu.
flowchart LR
subgraph Bridge["docker0 (bridge virtual)"]
direction LR
B("(docker0<br/>172.17.0.1")"))
end
C1["Container A<br/>172.17.0.2"] ---|veth| Bridge
C2["Container B<br/>172.17.0.3"] ---|veth| Bridge
C3["Container C<br/>172.17.0.4"] ---|veth| Bridge
Bridge ---|iptables NAT| Net[Host network]
Net --- Internet("(Internet"))
Karakteristik utama bridge network:
- Container punya IP private di subnet yang dikelola Docker (misal
172.17.0.0/16). - Container di bridge yang sama bisa saling bicara langsung (L2 forwarding).
- Container di bridge berbeda tidak bisa saling bicara tanpa routing eksplisit.
- Akses keluar (ke internet atau LAN) lewat NAT di iptables.
- Akses masuk (dari host atau luar) hanya lewat port mapping (
-p).
Bridge bukan hal baru di dunia Linux. Ia sudah ada sejak lama sebagai fitur brctl / iproute2. Docker hanya memaketkannya dengan rapi, ditambah integrasi dengan iptables, IPAM, dan DNS server internal.
Kenapa disebut “bridge”? Karena ia meng-copy behavior physical network bridge (layer-2 switch). Paket di-forward berdasarkan MAC address, bukan IP. Ini yang membuat komunikasi antar container sangat cepat untuk traffic internal.
Default Bridge vs User-Defined Bridge #
Docker menyediakan dua jenis bridge, dan perbedaan di antara keduanya adalah salah satu hal paling penting untuk dipahami.
Default Bridge (bridge)
#
Saat Docker Engine pertama kali berjalan, ia membuat satu bridge bawaan bernama bridge (di host, interface Linux-nya bernama docker0). Semua container yang dijalankan tanpa --network akan otomatis masuk ke bridge ini.
# Container otomatis masuk ke default bridge
docker run -d --name web nginx
# Lihat network tempat container terhubung
docker inspect web --format '{{.NetworkSettings.Networks}}'
Karakteristik default bridge:
| Aspek | Default Bridge |
|---|---|
| Nama network | bridge |
| Subnet | 172.17.0.0/16 (default) |
| DNS internal | ❌ Tidak ada |
| Resolusi nama | Hanya via IP atau link legacy |
| Isolasi | Semua container di bridge yang sama |
| Port mapping | Mendukung -p |
Keterbatasan terbesar: tidak ada DNS internal. Container web tidak bisa menghubungi container db dengan hostname db. Kamu harus tahu IP address-nya.
# Cara lama (tidak disarankan): hardcode IP
ping 172.17.0.3
Anti-pattern: Meninggalkan container di default bridge untuk aplikasi multi-container. Tidak ada DNS, tidak ada isolasi antar project, semua container berbagi satu subnet. Untuk eksperimen boleh; untuk aplikasi serius, jangan.
User-Defined Bridge (Direkomendasikan) #
Kamu bisa membuat bridge sendiri dengan docker network create. Inilah yang disebut user-defined bridge — dan ini yang harus kamu pakai untuk hampir semua skenario serius.
# Buat user-defined bridge
docker network create app-network
# Jalankan container di network itu
docker run -d --name web --network app-network nginx
docker run -d --name db --network app-network postgres
Sekarang web bisa menghubungi db cukup dengan hostname db:
docker exec web ping db
# PING db (172.18.0.3): 56 data bytes
# 64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.087 ms
Karakteristik user-defined bridge:
| Aspek | User-Defined Bridge |
|---|---|
| Nama | Bebas (misal app-network, backend-net) |
| Subnet | Otomatis atau custom (--subnet) |
| DNS internal | ✅ Otomatis aktif |
| Resolusi nama | Container name DAN alias |
| Isolasi | Per network, lebih terisolasi |
| Container di multiple network | ✅ Mendukung |
| Port mapping | Mendukung -p |
Best practice: Untuk setiap proyek multi-container, selalu buat user-defined bridge. Bahkan untuk dua container saja, lebih baik eksplisit. Ini melatih kamu untuk memikirkan topologi network, bukan asal docker run.
Perbandingan Langsung #
| Fitur | Default Bridge | User-Defined Bridge |
|---|---|---|
| DNS otomatis | ❌ | ✅ |
| Isolasi per project | ❌ (semua di satu bridge) | ✅ (network terpisah) |
| Container bisa di banyak network | ❌ | ✅ |
--link (legacy) |
✅ | ❌ (tidak diperlukan) |
| Custom subnet / gateway | ❌ | ✅ |
| Cocok untuk | Eksperimen, single container | Aplikasi multi-container |
Bagaimana Bridge Bekerja di Level OS #
Sekarang masuk ke bagian yang lebih teknis. Memahami apa yang terjadi di level OS membantu kamu debug saat ada masalah dan paham kenapa konfigurasi tertentu tidak berjalan seperti yang diharapkan.
1. Linux Bridge Interface #
Saat user-defined bridge dibuat, Docker membuat interface bridge di host:
docker network create app-network
ip link show
# br-abc123: <BROADCAST,MULTICAST,UP,LOWER_UP>
# inet 172.18.0.1/16 brd 172.18.255.255
Interface br-abc123 adalah bridge itu sendiri. Ia punya IP (gateway) dan akan menjadi titik koneksi semua container di network.
2. Network Namespace #
Setiap container berjalan di network namespace terpisah. Namespace ini punya:
- Interface sendiri (biasanya
eth0). - Routing table sendiri.
- Loopback
losendiri.
Container di network bridge yang sama berada di namespace berbeda, tapi terhubung lewat veth pair ke bridge yang sama.
3. Virtual Ethernet (veth) Pair #
Docker membuat veth pair untuk setiap container — dua interface virtual yang selalu terhubung:
- Ujung pertama masuk ke namespace container (muncul sebagai
eth0). - Ujung kedua tetap di namespace host, tercolok ke bridge.
flowchart LR
subgraph CN["Container Namespace"]
eth0["eth0"]
end
subgraph HN["Host Namespace"]
veth["veth-xxx@br-net"]
end
eth0 <-->|veth| veth
Paket yang dikirim container lewat eth0 akan muncul di ujung veth di host, lalu di-forward oleh bridge ke container tujuan.
4. IPAM (IP Address Management) #
Docker mengelola alokasi IP address container secara otomatis lewat IPAM driver. Untuk setiap network, IPAM:
- Menentukan subnet (default-nya random di range
172.x.0.0/16). - Memberi IP unik ke tiap container.
- Menentukan gateway.
Kamu bisa override:
docker network create \
--subnet=192.168.10.0/24 \
--gateway=192.168.10.1 \
--ip-range=192.168.10.0/25 \
custom-net
5. NAT dan iptables #
Agar container bisa keluar ke internet, Docker menambah aturan iptables MASQUERADE:
# Lihat rule NAT (simplified)
iptables -t nat -L POSTROUTING
# Chain POSTROUTING
# -A POSTROUTING -s 172.18.0.0/16 ! -o br-abc123 -j MASQUERADE
Artinya: paket dari subnet 172.18.0.0/16 yang keluar bukan lewat bridge itu sendiri akan di-MASQUERADE (source-nya diganti IP host). Hasilnya, dari sisi internet yang terlihat adalah host, bukan container.
Skema Lengkap di Level OS #
flowchart LR
subgraph CT["Container Namespace"]
E[eth0: 172.18.0.2]
end
subgraph HT["Host Namespace"]
V[veth-xxx@br-abc]
B[br-abc123: 172.18.0.1]
HV[eth0: 192.168.1.10]
end
subgraph K["Kernel"]
RT[Routing Table]
IPT[iptables NAT]
end
NET[Internet]
E <-->|l2| V
V --> B
B --> RT
RT --> IPT
IPT --> HV
HV --> NET
Saat container mengirim paket ke internet:
- Paket keluar dari container lewat
eth0. - veth meneruskan ke bridge.
- Bridge mem-lookup destination — bukan local, jadi diteruskan ke routing table.
- Routing table memutuskan lewat interface
eth0host. - iptables melakukan MASQUERADE — source IP diganti ke
192.168.1.10. - Paket keluar ke internet.
Saat balasan datang: proses kebalikannya. Paket di-DNAT balik ke IP container (172.18.0.2) dan di-forward lewat bridge.
Port Mapping pada Bridge #
Bridge network bersifat private — container di dalamnya tidak otomatis bisa diakses dari host atau internet. Untuk membuka akses, kamu butuh port mapping (-p / --publish).
docker run -d --name web -p 8080:80 nginx
Artinya: port 8080 di host di-forward ke port 80 di container.
sequenceDiagram
participant U as User
participant H as Host:8080
participant I as iptables DNAT
participant B as Bridge
participant C as Container:80
U->>H: GET localhost:8080
H->>I: Paket masuk
I->>I: DNAT: 8080 -> 172.18.0.2:80
I->>B: Forward
B->>C: Sampai di container
C-->>B: Response
B-->>I: Kembali
I-->>H: SNAT balik
H-->>U: HTTP response
Kamu juga bisa bind ke IP tertentu di host:
# Hanya localhost yang bisa akses
docker run -p 127.0.0.1:8080:80 nginx
# IP spesifik (misal IP LAN host)
docker run -p 192.168.1.10:8080:80 nginx
# Random port di host
docker run -p 80 nginx
Bahaya:-p 8080:80tanpa IP host akan bind ke0.0.0.0— artinya semua interface host menerima koneksi di port 8080. Kalau host punya IP publik, port ini akan terekspos ke internet. Untuk database atau service internal, selalu bind ke127.0.0.1.
Isolasi: Bridge Memberikan Batas Alami #
Salah satu kekuatan bridge network yang sering tidak disadari adalah isolasi default-nya. Container di bridge A tidak bisa bicara ke container di bridge B tanpa konfigurasi tambahan.
docker network create frontend
docker network create backend
docker run -d --name web --network frontend nginx
docker run -d --name db --network backend postgres
Sekarang web tidak bisa akses db lewat network (karena beda network). Untuk menghubungkan keduanya, kamu bisa:
# Connect container web ke backend juga
docker network connect backend web
Atau lebih aman: buat container terpisah yang berfungsi sebagai gateway, misalnya API service yang terhubung ke kedua network.
flowchart LR
subgraph Front["frontend network"]
W[web]
API[api]
end
subgraph Back["backend network"]
API2[api - same container]
DB["(db)"]
end
W --> API
API <--> API2
API2 --> DB
Container api punya dua interface — satu di frontend, satu di backend. Ia jadi jembatan yang bisa kamu kontrol, amati, dan audit. Database benar-benar tersembunyi dari frontend.
Bridge di Docker Compose #
Docker Compose secara default selalu membuat user-defined bridge untuk project. Kamu tidak perlu deklarasi network manual — Compose yang atur.
# docker-compose.yml
services:
web:
image: nginx
db:
image: postgres
api:
image: my-api
Tanpa deklarasi networks, Compose otomatis:
- Membuat satu network bernama
<project>_default. - Meng-connect-kan semua service ke network itu.
- Mengaktifkan DNS internal berbasis service name.
Hasilnya, web bisa bicara ke api dengan http://api:8080, dan api bisa bicara ke db dengan db:5432 — tanpa konfigurasi tambahan.
Kalau kamu butuh network custom atau multi-network:
version: "3.9"
services:
web:
image: nginx
networks:
- frontend
api:
image: my-api
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
networks:
frontend:
backend:
internal: true # tidak ada akses keluar ke internet
internal: true membuat network benar-benar terisolasi dari luar — tidak ada NAT keluar, tidak ada akses internet. Cocok untuk backend yang hanya boleh bicara ke service internal. Defense in depth murah tanpa extra config.
Kapan Bridge Network Tepat Digunakan #
Bridge network cocok untuk:
- Local development dengan satu host.
- Aplikasi multi-container (microservices) dalam satu host.
- CI/CD pipeline yang menjalankan test dalam container.
- Backend + database di satu server atau VM.
- Single-host production deployment untuk aplikasi skala kecil-menengah.
Bridge network kurang cocok untuk:
- Multi-host deployment (gunakan overlay untuk Swarm atau K8s).
- Performa jaringan ekstrem (gunakan host network).
- Sandbox tanpa network (gunakan none).
- Integrasi langsung ke LAN fisik (gunakan macvlan).
Anti-Pattern dan Solusinya #
Berikut tiga jebakan paling umum saat menggunakan bridge network, dan cara mengatasinya.
1. Meninggalkan Container di Default Bridge #
# ✗ Anti-pattern: container di default bridge, harus pakai IP
docker run -d --name db postgres
docker run -d --name api my-api
# api tidak bisa pakai "db", harus pakai IP
# ✓ Solusi: user-defined bridge, DNS otomatis
docker network create app-net
docker run -d --name db --network app-net postgres
docker run -d --name api --network app-net my-api
# api bisa pakai "db:5432"
2. Hardcode IP Container #
# ✗ Anti-pattern: hardcode IP
environment:
DATABASE_HOST: 172.18.0.3 # bisa berubah saat restart
# ✓ Solusi: pakai service name
environment:
DATABASE_HOST: db # DNS resolve otomatis
3. Pakai Host Network untuk Mikroservice #
# ✗ Anti-pattern: host network untuk banyak service
services:
web:
network_mode: host
db:
network_mode: host
# Port bentrok, tidak ada isolasi
# ✓ Solusi: user-defined bridge
services:
web:
networks: [app]
db:
networks: [app]
networks:
app:
Perintah Wajib untuk Bridge Network #
Sebelum lanjut, hafalkan perintah-perintah ini. Mereka akan jadi teman sehari-hari saat bekerja dengan bridge network.
# Lihat semua network (termasuk bridge default dan custom)
docker network ls
# Inspect detail satu network
docker network inspect app-network
# Akan menampilkan: subnet, gateway, container yang terhubung, IP per container
# Buat user-defined bridge dengan opsi lengkap
docker network create \
--driver bridge \
--subnet 192.168.50.0/24 \
--gateway 192.168.50.1 \
--ip-range 192.168.50.0/25 \
my-custom-bridge
# Hubungkan container yang sudah jalan ke network lain
docker network connect app-network existing-container
# Putuskan dari network
docker network disconnect app-network existing-container
# Hapus network (pastikan tidak ada container yang terhubung)
docker network rm app-network
# Prune: hapus semua network yang tidak terpakai
docker network prune
Trik debugging yang sering berguna:
docker network inspect <nama>→ lihat container mana saja yang terhubung dan IP-nya.brctl showatauip link showdi host → lihat bridge interface dan veth yang tercolok.iptables -t nat -L -n | grep <nama-network>→ lihat rule NAT untuk network tersebut.
Ringkasan #
- Bridge network adalah virtual switch layer-2 yang menghubungkan container di satu host. Ia adalah driver paling umum dan paling direkomendasikan untuk aplikasi single-host.
- Default bridge (
docker0) cocok untuk eksperimen, tapi tidak punya DNS internal dan semua container berbagi satu subnet.- User-defined bridge (
docker network create my-net) adalah pilihan serius: ada DNS internal berbasis nama container, isolasi per project, dan konfigurasi subnet/gateway yang fleksibel.- Di balik layar, bridge bekerja dengan empat komponen: namespace (isolasi), veth pair (kabel virtual), bridge interface (switch), dan iptables (NAT + firewall).
- Port mapping (
-p) membuka akses dari host ke container. Tanpa-p, container hanya bisa bicara ke container lain di network yang sama — bukan ke host atau internet.- Isolasi antar bridge adalah batas keamanan alami. Pisahkan frontend, backend, dan database ke network berbeda untuk defense in depth.
- Docker Compose selalu membuat user-defined bridge otomatis. Untuk multi-network atau
internal: true, deklarasi manual network.- Anti-pattern utama: tinggal di default bridge, hardcode IP, pakai host network untuk microservices.
- Bridge cocok untuk: local development, single-host deployment, microservices skala kecil-menengah, CI/CD. Kurang cocok untuk: multi-host, performa ekstrem, sandbox.