Volume & Network #

Volume dan network adalah dua konsep fundamental yang menentukan bagaimana container menyimpan data dan berkomunikasi. Docker Compose menyediakan cara deklaratif untuk mengelola keduanya, sehingga kamu bisa fokus pada aplikasi, bukan infrastruktur.

Artikel ini membahas semua jenis volume yang didukung Compose, topologi network yang tersedia, dan best practice untuk setup yang bersih.

Volume di Docker Compose #

Volume adalah mekanisme untuk menyimpan data di luar container. Ada tiga jenis utama: named volume, bind mount, dan tmpfs.

Named Volume #

Named volume di-manage oleh Docker, disimpan di /var/lib/docker/volumes/, dan portable antar host.

services:
  db:
    image: postgres:16-alpine
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

Pada contoh di atas, db-data adalah named volume. Docker membuatkannya otomatis (atau pakai yang sudah ada) dan mount ke /var/lib/postgresql/data di container db.

Karakteristik named volume:

  • Dikelola Docker — lifecycle, lokasi, dan cleanup di-manage oleh Docker.
  • Portable — bisa di-backup, di-restore, di-move antar host.
  • Aman untuk production — tidak bergantung pada layout filesystem host.
  • Bisa di-share antar service dengan me-mount volume yang sama.

Inspect named volume:

# List semua volume
docker volume ls

# Inspect volume tertentu
docker volume inspect myproject_db-data

# Lihat dimana data disimpan
docker volume inspect --format '{{ .Mountpoint }}' myproject_db-data
# Output: /var/lib/docker/volumes/myproject_db-data/_data

Bind Mount #

Bind mount me-mount direktori atau file dari host langsung ke dalam container.

services:
  web:
    volumes:
      - ./html:/usr/share/nginx/html:ro
      - /opt/configs/app:/etc/app:ro

Format: host_path:container_path:options.

Karakteristik bind mount:

  • Tergantung path host — harus ada di setiap host tempat stack dijalankan.
  • Performa native — akses langsung ke filesystem host, tidak ada layer abstraksi.
  • Cocok untuk development — source code di host bisa diedit dan langsung terlihat di container.
  • Tidak portable — struktur direktori host harus sama.

Untuk development:

services:
  api:
    build: ./api
    volumes:
      - ./api/src:/app/src      # hot reload
      - ./api/tests:/app/tests

Perubahan kode di host langsung terlihat di container. Untuk bahasa interpreted (Python, JavaScript, Ruby), ini artinya tidak perlu rebuild image.

Hati-hati permission. File di host mungkin di-own oleh user host, tapi di container di-own oleh user container. Untuk menghindari permission issue:

services:
  api:
    user: "1000:1000"  # samakan UID/GID dengan host
    volumes:
      - ./src:/app/src

Atau set permission di Dockerfile:

RUN chown -R 1000:1000 /app

tmpfs Mount #

tmpfs menyimpan data di memory (RAM), bukan disk. Data hilang saat container berhenti.

services:
  api:
    tmpfs:
      - /tmp:size=100m
      - /run

Karakteristik tmpfs:

  • Sangat cepat — RAM access.
  • Ephemeral — data hilang saat container stop/restart.
  • Tidak di-share antar container — masing-masing punya tmpfs sendiri.
  • Cocok untuk cache, session, file temporary processing.
Performance comparison: tmpfs (RAM) > local volume (SSD) > bind mount (host FS) > network volume (NFS/EFS). Pilih sesuai kebutuhan performa dan persistence.

Volume Driver #

Named volume mendukung driver untuk backend storage yang berbeda.

volumes:
  db-data:
    driver: local
    driver_opts:
      type: nfs
      o: addr=10.0.0.5,rw
      device: ":/path/to/dir"
  
  shared-data:
    driver: aws/efs
    driver_opts:
      efs.id: fs-12345678

Driver yang umum:

  • local — default, simpan di host local.
  • nfs — Network File System, shared storage.
  • aws/efs — AWS Elastic File System.
  • gcs — Google Cloud Storage (FUSE).
  • azurefile — Azure File Storage.
Network volume driver (NFS, EFS) menambah latency dan potensi failure point. Untuk database production, lebih baik local SSD dengan replication di level aplikasi.

Network di Docker Compose #

Compose otomatis membuat network internal dan mendaftarkan semua service di dalamnya. Service bisa saling komunikasi via hostname = nama service.

Default Network #

Saat kamu tidak mendefinisikan network, Compose membuat satu network default.

services:
  api:
    image: myapi
  
  db:
    image: postgres:16

Docker membuat network myproject_default dan kedua service join ke sana. api bisa resolve db via hostname.

Inspect:

docker network ls
docker network inspect myproject_default

Custom Network #

Untuk kontrol lebih, definisikan network eksplisit.

services:
  nginx:
    networks:
      - frontend
  
  api:
    networks:
      - frontend
      - backend
  
  db:
    networks:
      - backend

networks:
  frontend:
  backend:
    driver: bridge

Pada konfigurasi ini:

  • nginx dan api ada di frontend. Mereka bisa komunikasi.
  • api dan db ada di backend. Mereka bisa komunikasi.
  • db tidak ada di frontend, jadi nginx tidak bisa langsung akses db.
  • Semua harus lewat api.

Ini adalah pattern defense in depth — pisahkan service publik dari service internal.

Network Driver #

Default driver untuk custom network di Compose adalah bridge. Driver lain juga tersedia.

networks:
  frontend:
    driver: bridge
  
  backend:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br-backend
    attachable: true

bridge driver di Linux menggunakan bridge interface di kernel. driver_opts memungkinkan konfigurasi tingkat lanjut.

Driver lain:

  • host — share network namespace dengan host. Tidak ada network isolation.
  • overlay — untuk multi-host (Swarm mode).
  • macvlan — assign MAC address ke container, terlihat sebagai device fisik.
Untuk Compose single host, bridge sudah cukup. Driver lain dibutuhkan untuk kasus khusus: host untuk performance network-sensitive, overlay untuk multi-host (Swarm), macvlan untuk integrasi dengan network fisik.

Network Aliases #

Service bisa punya beberapa hostname di network.

services:
  api:
    networks:
      frontend:
        aliases:
          - api-service
          - myapi
          - backend-api

api sekarang bisa di-reach via api, api-service, myapi, atau backend-api di network frontend. Berguna untuk compatibility dengan kode lama yang hardcode hostname tertentu.

External Network #

Untuk menghubungkan stack Compose dengan resource di luar Compose.

services:
  api:
    networks:
      - shared-network

networks:
  shared-network:
    external: true
    name: my-existing-network

Network my-existing-network sudah ada di Docker (dibuat manual atau oleh stack lain). Compose tidak akan menghapusnya saat down.

Use case:

  • Stack yang dibagi antar multiple Compose project.
  • Network monitoring atau logging yang berdiri sendiri.
  • Service legacy yang di-manage di luar Compose.

Contoh Setup Lengkap #

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
      - html:/usr/share/nginx/html
    networks:
      - frontend
    depends_on:
      - api
    restart: unless-stopped

  api:
    build: ./api
    environment:
      - DATABASE_URL=postgres://app:secret@db:5432/myapp
      - REDIS_URL=redis://cache:6379
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_healthy
    networks:
      - frontend
      - backend
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      - POSTGRES_USER=app
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=myapp
    volumes:
      - pg-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend
    restart: unless-stopped

  cache:
    image: redis:7-alpine
    volumes:
      - cache-data:/data
    networks:
      - backend
    restart: unless-stopped

  worker:
    build: ./worker
    environment:
      - DATABASE_URL=postgres://app:secret@db:5432/myapp
    networks:
      - backend
    restart: unless-stopped

volumes:
  pg-data:
  cache-data:
  html:

networks:
  frontend:
  backend:
    internal: false  # expose ke host? atau biarkan false

Stack ini punya 5 service, 3 named volume, 2 network. Database dan cache di-isolate di backend. Hanya nginx yang di-expose ke host via ports.

Best Practice #

Gunakan Named Volume untuk Data #

Named volume adalah default yang aman. Ia portable, di-manage Docker, dan mendukung backup.

# BAGUS
volumes:
  - db-data:/var/lib/postgresql/data

# HINDARI untuk production
volumes:
  - /var/lib/postgresql/data:/var/lib/postgresql/data

Bind mount ke absolute path di host rapuh — kalau host berbeda layout, container gagal start.

Bind Mount untuk Development #

Untuk development, bind mount source code biar hot-reload jalan.

# docker-compose.dev.yml
services:
  api:
    volumes:
      - ./src:/app/src  # hot reload
      - /app/node_modules  # exclude dari bind mount

/app/node_modules di-mount sebagai anonymous volume untuk mencegah host’s node_modules (kalau ada) override container’s.

Pisahkan Network Sesuai Peran #

networks:
  public:    # di-expose ke internet
  internal:  # service-to-service only
  management: # monitoring, debugging

Pisahkan network berdasarkan siapa yang boleh akses. Database jangan pernah di public network.

Set Resource Limits #

Untuk container yang mount banyak data atau share network besar.

services:
  db:
    volumes:
      - db-data:/var/lib/postgresql/data
    deploy:
      resources:
        limits:
          memory: 4G

Backup Volume #

Pakai container terpisah untuk backup.

# Backup volume ke file
docker run --rm \
  -v myproject_pg-data:/source:ro \
  -v $(pwd)/backups:/backup \
  alpine tar -czf /backup/pg-data-$(date +%F).tar.gz -C /source .

# Restore dari file
docker run --rm \
  -v myproject_pg-data:/target \
  -v $(pwd)/backups:/backup:ro \
  alpine tar -xzf /backup/pg-data-2024-01-15.tar.gz -C /target
Clean separation: data via volume, service via Compose, backup via separate container. Ini memungkinkan backup tanpa mengganggu service, dan service bisa di-recreate tanpa kehilangan data.

Tabel Referensi Volume Mount #

Referensi cepat untuk semua cara mount volume di Compose.

Tipe Syntax Contoh
Named volume name:path db-data:/var/lib/data
Named volume (eksplisit) type:volume,source:...,target:... Long form
Bind mount host:path:container:path ./src:/app/src
Bind mount (eksplisit) type:bind,source:...,target:... Long form
tmpfs (shorthand) - /tmp - /tmp
tmpfs (eksplisit) type:tmpfs,target:... Long form
Anonymous volume - /var/lib/data - /var/lib/data

Contoh long-form syntax:

volumes:
  # Named volume
  - type: volume
    source: db-data
    target: /var/lib/postgresql/data

  # Bind mount dengan read-only
  - type: bind
    source: ./configs
    target: /etc/app/configs
    read_only: true

  # tmpfs dengan size limit
  - type: tmpfs
    target: /tmp
    tmpfs:
      size: 100m

Long-form berguna untuk opsi yang tidak ada di shorthand, seperti bind propagation, tmpfs.size, atau volume nocopy.

Tabel Referensi Network #

Tipe Syntax Contoh
Default network (otomatis) Otomatis dibuat
Custom network name: ... di top-level frontend: ...
External network external: true external: true, name: my-net
Network dengan driver driver: ... driver: bridge
Network dengan subnet ipam: ... ipam: { config: [...] }

Network dengan static IP:

networks:
  backend:
    ipam:
      driver: default
      config:
        - subnet: 10.5.0.0/16

services:
  db:
    networks:
      backend:
        ipv4_address: 10.5.0.5

Berguna untuk service yang butuh IP tetap — biasanya untuk legacy yang hardcode IP.

Volume Lifecycle Management #

Prune Unused Volumes #

# Hapus volume yang tidak di-mount ke container manapun
docker volume prune

# Hapus semua volume yang tidak ada di Compose file
docker compose down --volumes

docker compose down --volumes menghapus semua volume yang dideklarasikan di Compose file. Lebih aman dari docker volume prune --all.

Backup Strategy #

Backup harus jadi bagian dari operational routine. Contoh script untuk Postgres:

#!/bin/bash
BACKUP_DIR="/backups/$(date +%F)"
mkdir -p "$BACKUP_DIR"

# Backup database dengan pg_dump
docker compose exec -T db pg_dump -U app myapp | gzip > "$BACKUP_DIR/db.sql.gz"

# Backup raw volume (untuk file-based data, bukan database)
docker run --rm \
  -v myproject_pg-data:/source:ro \
  -v "$BACKUP_DIR":/backup \
  alpine tar -czf /backup/pg-data.tar.gz -C /source .

# Upload ke S3
aws s3 sync "$BACKUP_DIR" "s3://my-backups/$(date +%F)/"

Test restore procedure secara berkala — backup yang tidak pernah di-restore tidak ada gunanya.

Untuk database, pakai pg_dump/mysqldump daripada copy volume langsung. Database punya internal state (WAL, redo log, dll) yang harus konsisten. pg_dump memastikan snapshot yang konsisten. Copy raw volume bisa menghasilkan backup yang corrupt.

Migration Volume #

Untuk pindah volume antar host atau cloud.

# Stop service yang pakai volume
docker compose stop db

# Export volume ke file
docker run --rm \
  -v myproject_pg-data:/from:ro \
  -v $(pwd):/to \
  alpine tar -czf /to/pg-data.tar.gz -C /from .

# Transfer file ke host baru (scp, rsync, dll)
rsync -avz pg-data.tar.gz user@newhost:/tmp/

# Di host baru, import
docker volume create pg-data
docker run --rm \
  -v pg-data:/to \
  -v /tmp:/from:ro \
  alpine tar -xzf /from/pg-data.tar.gz -C /to

# Start service di host baru
docker compose up -d db

Network Performance Tuning #

MTU dan Driver #

Default MTU untuk bridge network adalah 1500. Untuk network dengan encapsulation overhead (overlay, VXLAN), kamu mungkin perlu turunkan.

networks:
  backend:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.mtu: 1450

DNS Resolution #

Compose otomatis setup DNS untuk service di network. Resolution terjadi via Docker’s embedded DNS server.

# Test DNS resolution dari dalam container
docker compose exec api nslookup db
docker compose exec api nslookup redis

Jika nslookup gagal, biasanya ada masalah dengan network setup atau service tidak di network yang sama.

Connection Limits #

Untuk high-traffic service, tune ulimits (file descriptor).

services:
  api:
    ulimits:
      nofile:
        soft: 65536
        hard: 65536

Atau tune sysctl dalam container (kalau image mendukung):

services:
  api:
    sysctls:
      - net.core.somaxconn=1024
      - net.ipv4.tcp_max_syn_backlog=1024
Default network Compose cukup untuk kebanyakan kasus. Tuning MTU, ulimits, dan sysctls adalah optimasi untuk high-performance workload. Untuk development dan small production, default sudah lebih dari cukup.

Recap Cheatsheet #

Aspek Rekomendasi
Data persisten Named volume
Source code di host Bind mount
Cache ephemeral tmpfs
Network default Otomatis
Multi-tier isolation Custom network per peran
Backup Container terpisah + upload ke S3
Prune docker compose down --volumes
Production driver local (SSD) atau managed DB

Ringkasan #

  • Volume adalah cara Docker menyimpan data di luar container. Tiga jenis: named volume, bind mount, tmpfs.
  • Named volume adalah default yang aman — portable, di-manage Docker, support backup. Gunakan untuk data persisten (database, upload).
  • Bind mount untuk development (source code hot-reload) atau konfigurasi yang perlu akses langsung dari host. Hindari untuk production karena tidak portable.
  • tmpfs untuk data ephemeral di memory. Sangat cepat tapi hilang saat restart.
  • Network di Compose otomatis dibuat. Service di file yang sama bisa saling resolve via hostname.
  • Custom network untuk pisahkan service sesuai peran (public, internal, management). Defense in depth.
  • Network driver bridge untuk single host. overlay untuk multi-host (Swarm). host untuk performance.
  • Aliases untuk multiple hostname di satu network. External network untuk integrasi dengan resource di luar Compose.
  • Backup volume via container terpisah. Restore juga via container, bukan langsung edit di host.
  • Best practice: named volume untuk data, bind mount untuk development code, pisahkan network per peran, set resource limits, dan punya backup strategy.

← Sebelumnya: Environment Variable   Berikutnya: Depends On →

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