Aplikasi modern jarang berdiri sendiri. Blog butuh database. API butuh Redis untuk caching. Microservice butuh message broker. Mengelola semua container ini secara manual dengan perintah docker run yang panjang akan sangat melelahkan.
Docker Compose hadir sebagai solusinya — sebuah tool untuk mendefinisikan dan menjalankan aplikasi multi-container menggunakan satu file YAML sederhana.
Apa itu Docker Compose?
Docker Compose memungkinkan kamu mendefinisikan seluruh stack aplikasi (semua service, network, dan volume) dalam file docker-compose.yml. Lalu dengan satu perintah, semua service bisa dijalankan, dihentikan, dan dikelola sekaligus.
docker compose up # jalankan semua service
docker compose down # hentikan dan hapus semua
Anatomi docker-compose.yml
version: '3.8' # versi syntax Compose
services: # daftar container yang akan dijalankan
nama-service:
image: nama-image
build: ./path # atau build dari Dockerfile
ports:
- "host:container"
environment:
- KEY=VALUE
volumes:
- host:container
depends_on:
- service-lain
networks:
- nama-network
volumes: # definisi named volumes
nama-volume:
networks: # definisi custom network
nama-network:
Contoh: API Node.js + PostgreSQL + Redis
Ini adalah setup yang sangat umum untuk aplikasi web modern.
docker-compose.yml:
version: '3.8'
services:
# Aplikasi Node.js
api:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- DATABASE_URL=postgresql://dev_user:dev_pass@db:5432/dev_db
- REDIS_URL=redis://cache:6379
volumes:
- .:/app
- /app/node_modules # jangan mount node_modules dari host
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
restart: unless-stopped
# PostgreSQL
db:
image: postgres:16-alpine
ports:
- "5432:5432" # expose ke host untuk akses tools (opsional)
environment:
POSTGRES_USER: dev_user
POSTGRES_PASSWORD: dev_pass
POSTGRES_DB: dev_db
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U dev_user -d dev_db"]
interval: 10s
timeout: 5s
retries: 5
# Redis
cache:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes
volumes:
postgres_data:
redis_data:
Perintah-Perintah Docker Compose
# Jalankan semua service (foreground)
docker compose up
# Jalankan di background
docker compose up -d
# Build ulang image sebelum start (saat Dockerfile berubah)
docker compose up --build
# Hentikan service tanpa hapus container
docker compose stop
# Hentikan DAN hapus container, network (data di volume tetap ada)
docker compose down
# Hentikan, hapus container + volume (data hilang!)
docker compose down -v
# Lihat status semua service
docker compose ps
# Lihat log semua service
docker compose logs
# Lihat log service tertentu secara live
docker compose logs -f api
# Eksekusi perintah di dalam service yang berjalan
docker compose exec api sh
docker compose exec db psql -U dev_user dev_db
# Jalankan satu kali perintah di service (tanpa service harus running)
docker compose run --rm api npm run migrate
# Restart satu service
docker compose restart api
# Scale service (jalankan beberapa instance)
docker compose up -d --scale api=3
Environment Variables dengan .env
Jangan hardcode nilai sensitif di docker-compose.yml. Gunakan file .env:
.env:
POSTGRES_USER=dev_user
POSTGRES_PASSWORD=dev_pass
POSTGRES_DB=dev_db
APP_PORT=3000
docker-compose.yml — referensikan dengan ${VAR}:
services:
api:
ports:
- "${APP_PORT}:3000"
db:
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
Tambahkan .env ke .gitignore dan sediakan .env.example sebagai template.
Multiple Compose Files
Gunakan file compose terpisah untuk development dan production:
docker-compose.yml (base):
services:
api:
image: blog-api
environment:
- NODE_ENV=production
docker-compose.override.yml (development — otomatis dipakai):
services:
api:
build: .
environment:
- NODE_ENV=development
volumes:
- .:/app
docker-compose.prod.yml (production):
services:
api:
image: registry.io/blog-api:latest
restart: always
deploy:
replicas: 3
# Development (pakai base + override otomatis)
docker compose up
# Production (tentukan file secara eksplisit)
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Health Check dan depends_on
depends_on memastikan urutan startup, tapi tidak menjamin service sudah siap — hanya sudah berjalan. Gunakan healthcheck untuk memastikan service benar-benar siap sebelum service lain dimulai:
db:
image: postgres:16-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
api:
depends_on:
db:
condition: service_healthy # tunggu hingga db healthy
Kesimpulan
Docker Compose mengubah pengelolaan multi-container dari sesuatu yang rumit menjadi sangat sederhana. Dengan satu file docker-compose.yml, seluruh stack aplikasi bisa dijalankan, dihentikan, dan dikelola konsisten oleh semua anggota tim.
Di artikel berikutnya, kita bahas Docker Volume dan Network — cara data persisten dan komunikasi antar container bekerja.
Kiki/🎮🍉⌨️🍩💻
Dockerfile: Cara Membuat Docker Image Sendiri