User-defined Network #

Jika ada satu konsep di Docker networking yang wajib dikuasai untuk aplikasi production, itu adalah user-defined network. Docker menyediakan banyak network driver, tapi untuk hampir semua skenario single-host, user-defined bridge adalah pilihan terbaik. Ia menggabungkan semua yang kita butuhkan: DNS internal, isolasi yang baik, konfigurasi fleksibel, dan service discovery yang stabil.

Banyak developer masih menggunakan default bridge (docker0) tanpa sadar keterbatasannya — tidak ada DNS internal, semua container di satu subnet, dan komunikasi antar container harus pakai IP address. User-defined network menyelesaikan semua masalah itu dengan satu perintah: docker network create.

Artikel ini membahas user-defined network secara mendalam: cara membuat, opsi konfigurasi (subnet, gateway, internal), multi-network per container, integrasi dengan Docker Compose, dan pola arsitektur untuk aplikasi production. Pada akhirnya, kamu akan bisa merancang topologi network container yang aman, scalable, dan mudah di-maintain.

Apa Itu User-defined Network? #

User-defined network adalah network yang kamu buat secara eksplisit dengan docker network create, bukan network bawaan yang otomatis dibuat Docker (bridge, host, none).

# Buat user-defined network
docker network create my-network

# Lihat semua network
docker network ls
# NETWORK ID     NAME          DRIVER    SCOPE
# abc123...      bridge        bridge    local  <- default
# def456...      host          host      local  <- default
# ghi789...      none          null      local  <- default
# jkl012...      my-network    bridge    local  <- kamu yang buat

Karakteristik user-defined network (default driver bridge):

  • DNS internal otomatis — container bisa saling resolve via nama.
  • Isolasi per network — container di network A tidak bicara ke network B.
  • Container di banyak network — satu container bisa multi-network.
  • Konfigurasi custom — subnet, gateway, IP range, driver tertentu.
  • Service discovery — Compose otomatis pakai user-defined network.
User-defined network = best practice default. Untuk hampir semua kasus, docker network create my-net dan jalankan container di network itu. Default bridge hanya untuk eksperimen cepat.

Cara Membuat User-defined Network #

Sintaks Dasar #

docker network create [OPTIONS] NETWORK_NAME

Opsi yang paling sering dipakai:

Opsi Fungsi
--driver Tipe driver (default: bridge)
--subnet Custom subnet (CIDR)
--gateway Custom gateway IP
--ip-range Range IP untuk container
--internal Network tanpa akses keluar
--attachable Container bisa di-attach manual
--label Metadata (untuk Compose, K8s)

Contoh #

# Paling sederhana - Docker pilih semua default
docker network create app-network

# Custom subnet
docker network create \
  --subnet=192.168.50.0/24 \
  --gateway=192.168.50.1 \
  custom-net

# Internal network (tidak ada akses internet)
docker network create --internal backend-net

# Multi-driver (overlay untuk Swarm)
docker network create --driver overlay swarm-net

Mengapa Default Bridge Tidak Cukup #

Default bridge (docker0) adalah bridge bawaan yang dibuat saat Docker Engine pertama kali install. Ia punya keterbatasan serius untuk aplikasi multi-container.

Aspek Default Bridge User-defined Network
DNS internal ❌ Tidak ✅ Ya
Container name resolve ❌ (harus IP atau --link)
Service name (Compose)
Isolasi antar project ❌ (semua di satu bridge)
Multi-network per container
Custom subnet
Container scaling Terbatas Bebas
# Default bridge - DNS tidak aktif
docker run -d --name web --network bridge nginx
docker run -d --name db  --network bridge postgres
docker exec web sh -c 'ping -c 1 db'
# ping: bad address 'db'  <- GAGAL

# User-defined - DNS aktif
docker network create app-net
docker run -d --name web --network app-net nginx
docker run -d --name db  --network app-net postgres
docker exec web sh -c 'ping -c 1 db'
# PING db (172.18.0.2): 56 data bytes  <- BERHASIL
Default bridge = anti-pattern untuk aplikasi multi-container. Jangan pakai untuk apa pun selain testing cepat atau container single yang berdiri sendiri.

Konfigurasi Custom Subnet dan Gateway #

Untuk kontrol lebih, kamu bisa set subnet, gateway, dan IP range sendiri.

docker network create \
  --driver bridge \
  --subnet 10.10.0.0/16 \
  --gateway 10.10.0.1 \
  --ip-range 10.10.1.0/24 \
  --label env=production \
  --label app=backend \
  production-backend

Kapan perlu custom subnet?

  • Avoid conflict dengan network lain — kalau host punya VPN dengan subnet 192.168.0.0/16, dan Docker default juga di range itu, bisa bentrok.
  • Predictable IP allocation — kalau kamu butuh container punya IP tertentu untuk alasan compliance.
  • Multi-host setup — subnet yang terstruktur memudahkan routing.
# Inspect detail
docker network inspect production-backend

Output akan menunjukkan IPAM.Config dengan Subnet, Gateway, dan IPRange yang sudah di-custom.

Best practice: gunakan subnet yang mudah diingat dan tidak bentrok dengan range umum (10.0.0.0/8 besar sekali, 172.16.0.0/12 medium, 192.168.0.0/16 kecil). Hindari 192.168.0.0/24 dan 192.168.1.0/24 karena bentrok dengan router rumah/kantor.

Internal Network: Total Isolasi dari Internet #

User-defined network bisa dibuat internal — tanpa gateway keluar, tanpa akses internet, tanpa NAT keluar.

docker network create --internal backend-net

Karakteristik internal network:

  • Tidak ada gateway di routing table container.
  • Container tidak bisa akses internet — DNS ke 8.8.8.8 juga gagal.
  • Container tetap bisa bicara ke container lain di network yang sama.
  • Cocok untuk: database, cache, message broker, internal service.
# docker-compose.yml
networks:
  backend:
    internal: true
  frontend:
    # Default - ada akses internet
# Verifikasi: container di internal network tidak bisa ping google
docker run --rm --network backend-net alpine ping -c 1 8.8.8.8
# ping: connect: Network is unreachable
Internal network = no internet, no exceptions. Ini bukan fitur yang bisa di-bypass. Kalau service di internal network tiba-tiba bisa akses internet, ada misconfiguration. Audit konfigurasi Docker dan iptables.

Multi-Network per Container: Layered Security #

Satu container bisa terhubung ke banyak user-defined network sekaligus. Ini adalah pola layered security yang umum.

# Container API yang bridge antara frontend dan backend
docker network create frontend
docker network create backend --internal

docker run -d --name api --network frontend my-api
docker network connect backend api
flowchart LR
    subgraph Front["frontend (public)"]
        W[web]
        A[api]
    end
    subgraph Back["backend (internal)"]
        A
        D[(db)]
    end
    W --> A
    A --> D

Container api punya interface di frontend (terbuka ke internet) dan backend (internal, tersembunyi). Ia jadi satu-satunya gateway. Database benar-benar tersembunyi — tidak bisa di-reach dari internet tanpa lewat api.

# docker-compose.yml - pola segmentasi
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

User-defined Network di Docker Compose #

Docker Compose selalu membuat user-defined network untuk project, kecuali kamu override.

version: "3.9"
services:
  web:
    image: nginx
  api:
    image: my-api
  db:
    image: postgres

Tanpa deklarasi networks, Compose otomatis:

  • Membuat satu network default: <project>_default (misal myapp_default).
  • Connect-kan semua service ke network itu.
  • Aktifkan DNS internal berbasis service name.
docker compose up -d
docker network ls
# myapp_default    bridge    local  <- dibuat otomatis

docker network inspect myapp_default
# Containers:
#   - myapp-web-1
#   - myapp-api-1
#   - myapp-db-1

Multi-Network Custom di Compose #

version: "3.9"
services:
  web:
    image: nginx
    networks:
      - frontend
  
  api:
    image: my-api
    networks:
      - frontend
      - backend
  
  worker:
    image: my-worker
    networks:
      - backend
  
  db:
    image: postgres
    networks:
      - backend

networks:
  frontend:
    name: my-frontend
  backend:
    name: my-backend
    internal: true
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br-backend
driver_opts.com.docker.network.bridge.name memungkinkan kamu set nama interface Linux bridge. Berguna untuk monitoring (tcpdump -i br-backend) atau audit (ip link show di host).

User-defined Network untuk Multi-Host (Swarm) #

Untuk deployment multi-host, user-defined network bisa dibuat dengan driver overlay di Docker Swarm.

docker network create \
  --driver overlay \
  --subnet 10.0.0.0/16 \
  --attachable \
  swarm-net

Container yang di-deploy di Swarm otomatis tersebar di banyak host, tapi masih dalam satu network. Komunikasi lewat VXLAN tunnel di bawah.

flowchart LR
    subgraph Host1["Host 1"]
        C1A[Container A]
        C1B[Container B]
    end
    subgraph Host2["Host 2"]
        C2A[Container A]
        C2B[Container C]
    end
    subgraph Host3["Host 3"]
        C3A[Container C]
    end
    C1A <-->|VXLAN| C2A
    C1B <-->|VXLAN| C2B
    C2B <-->|VXLAN| C3A
# docker-stack.yml (Swarm mode)
version: "3.9"
services:
  web:
    image: nginx
    networks:
      - frontend
    deploy:
      replicas: 5
  
  api:
    image: my-api
    networks:
      - frontend
      - backend
    deploy:
      replicas: 10

networks:
  frontend:
    driver: overlay
  backend:
    driver: overlay
    internal: true

Container web di host berbeda tetap bisa saling menemukan via web (Swarm DNS load-balances ke replica terdekat). api di host berbeda bisa bicara ke db yang mungkin ada di host lain.


Topologi Arsitektur Umum #

Tier Tunggal: Single Network #

flowchart LR
    N[app-network] --> W[web]
    N --> A[api]
    N --> D[(db)]
    N --> C[(cache)]

Cocok untuk: development, single-host, MVP.

Tiga Tier: Edge-App-Data #

flowchart TB
    subgraph Edge["edge"]
        LB[Load Balancer]
    end
    subgraph App["app"]
        API[API]
        W1[Worker]
    end
    subgraph Data["data (internal)"]
        DB[(DB)]
        Cache[(Cache)]
        Broker[(Kafka)]
    end
    LB --> API
    API --> DB
    API --> Cache
    W1 --> Broker
    Broker --> DB

Cocok untuk: production single-host, multi-service dengan segmentasi.

Multi-Tenant: Per-Tenant Network #

flowchart TB
    subgraph A["tenant-a"]
        AN[a-network]
        A1[app]
        A2[(db)]
    end
    subgraph B["tenant-b"]
        BN[b-network]
        B1[app]
        B2[(db)]
    end
    Admin[admin-network] --> A1
    Admin --> B1

Cocok untuk: SaaS, hosting environment, dev/staging/prod per customer.

Microservices dengan Broker #

flowchart LR
    subgraph Edge["edge"]
        GW[Gateway]
    end
    subgraph App["app"]
        API1[API Service]
        API2[Worker]
    end
    subgraph Broker["broker"]
        K[(Kafka)]
    end
    subgraph Data["data"]
        DB1[(DB 1)]
        DB2[(DB 2)]
    end
    GW --> API1
    API1 --> K
    K --> API2
    API1 --> DB1
    API2 --> DB2

Cocok untuk: event-driven architecture, microservices besar.


Mengelola User-defined Network #

Inspeksi #

# Lihat semua network
docker network ls

# Detail network
docker network inspect my-network
# Berisi: driver, subnet, gateway, containers yang terhubung

# Lihat hanya container di network
docker network inspect my-network --format '{{range .Containers}}{{.Name}} {{end}}'

# IP satu container
docker network inspect my-network --format '{{json .Containers}}' | python3 -c "import json,sys; print(json.load(sys.stdin)['container-id']['IPv4Address'])"

Modifikasi #

# Hubungkan container ke network
docker network connect my-network existing-container

# Putuskan
docker network disconnect my-network existing-container

# Hapus network (harus tidak ada container)
docker network rm my-network

Cleanup #

# Hapus semua network yang tidak terpakai
docker network prune

# Hapus semua container + network
docker system prune --volumes
docker network rm gagal kalau masih ada container yang terhubung. Lepaskan container dulu (disconnect) atau hapus container-nya. Di Compose, docker compose down otomatis hapus network project.

User-defined Network vs Default Bridge: Kapan Pakai Yang Mana #

Situasi Pilihan
Eksperimen cepat 1 container Default bridge (atau tidak perlu network sama sekali)
Multi-container development User-defined network
Production dengan banyak service User-defined network + segmentasi
Multi-host (Swarm, K8s) User-defined network dengan driver overlay/calico
Sandbox tanpa network None network
High-performance Host network (tapi hati-hati)

Praktis: untuk 95% kasus, user-defined bridge adalah pilihan benar. Sisanya 5% adalah kasus khusus yang memang butuh mode lain.


Best Practice User-defined Network #

1. Selalu Pakai User-defined untuk Multi-Container #

# ✓ Best practice
docker network create app-net
docker run --network app-net --name db postgres
docker run --network app-net --name api my-api

2. Segmentasi Berdasarkan Layer #

networks:
  edge:        # public-facing
  app:         # business logic
  data:        # internal: true, no internet

3. Pakai Nama Network yang Deskriptif #

# ✓ Bagus
docker network create frontend-prod
docker network create backend-prod
docker network create data-prod

# ✗ Kurang bagus
docker network create net1
docker network create net2

4. Custom Subnet untuk Hindari Konflik #

# Hindari range umum 192.168.x.x (rumah) dan 10.x.x.x (banyak dipakai)
docker network create --subnet 172.25.0.0/16 app-net

5. Internal Network untuk Service Sensitif #

networks:
  data:
    internal: true  # database, cache, broker

6. Docker Compose: Biarkan Default, atau Custom Eksplisit #

# Default (Compose auto-create satu network)
services:
  web:
  api:

# Custom eksplisit (untuk kontrol penuh)
services:
  web:
    networks: [frontend]
  api:
    networks: [frontend, backend]
networks:
  frontend:
  backend:
    internal: true

7. Cleanup Rutin #

# Hapus network orphaned
docker network prune

# Atau semua unused sekaligus
docker system prune

Migrasi dari Default Bridge ke User-defined #

Kalau proyekmu sudah terlanjur pakai default bridge, migrasinya mudah:

# 1. Buat user-defined network
docker network create app-net

# 2. Hubungkan semua container yang ada
for container in web api db; do
  docker network connect app-net $container
done

# 3. Test komunikasi
docker exec web ping api

# 4. Update docker-compose.yml untuk masa depan
# Update docker-compose.yml
version: "3.9"
services:
  web:
    networks: [app-net]
  api:
    networks: [app-net]
  db:
    networks: [app-net]

networks:
  app-net:

Ringkasan #

  • User-defined network = network yang kamu buat sendiri dengan docker network create. Ia mengatasi semua keterbatasan default bridge.
  • Wajib pakai untuk aplikasi multi-container, production, atau yang butuh service discovery via nama.
  • DNS internal otomatis — container resolve nama container atau service name tanpa konfigurasi tambahan.
  • Konfigurasi lengkap: --subnet, --gateway, --ip-range, --internal, --driver, --label. Subnet custom menghindari konflik dengan network host.
  • Internal network = tidak ada akses internet. Wajib untuk database, cache, broker, dan service yang tidak boleh punya akses keluar.
  • Multi-network per container memungkinkan layered security: container API di frontend dan backend, jadi gateway yang bisa diaudit.
  • Docker Compose otomatis membuat user-defined network. Untuk kontrol penuh, deklarasi networks: di Compose dan assign per-service.
  • Multi-host (Swarm, K8s): user-defined network dengan driver overlay, atau driver eksternal (Calico, Flannel, Cilium).
  • Default bridge = anti-pattern untuk multi-container. Hanya untuk eksperimen cepat atau single container.
  • Best practice: segmentasi per layer (edge/app/data), nama network deskriptif, internal untuk service sensitif, custom subnet untuk hindari konflik.
  • Prinsip utama: container yang bekerja sama → user-defined network. Container standalone → default bridge cukup. Container publik → port mapping minimal dan segmentasi jelas.
  • Migrasi dari default bridge ke user-defined mudah: create network, connect existing container, update Compose.

← Sebelumnya: Network Isolation   Berikutnya: Apa itu Dockerfile? →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact