Compose Watch — Hot Reload Tanpa Bind Mount
Cara lama memakai bind mount seluruh direktori, yang menimbulkan masalah: node_modules di host bentrok dengan yang di kontainer, kinerja berkas di macOS dan Windows sangat lambat, dan izin berkas sering kacau.
services:
web:
build: .
ports: ["3000:3000"]
develop:
watch:
# Salin berkas ke kontainer tanpa restart
- action: sync
path: ./src
target: /app/src
ignore: [node_modules/]
# Bangun ulang image bila dependensi berubah
- action: rebuild
path: ./package.json
# Salin lalu restart proses
- action: sync+restart
path: ./config
target: /app/config
docker compose watch
📌 Tiga aksi dan kapan memakainya
sync— untuk berkas yang ditangani hot-reload aplikasi (React, nodemon, uvicorn --reload).sync+restart— untuk berkas konfigurasi yang hanya dibaca saat proses menyala.rebuild— untuk manifest dependensi sepertipackage.json,go.mod,requirements.txt.
Profil — Satu Berkas untuk Banyak Skenario
services:
api:
build: .
# tanpa profiles -- selalu ikut berjalan
db:
image: postgres:17-alpine
# Hanya menyala bila diminta
pgadmin:
image: dpage/pgadmin4
profiles: ["alat"]
mailhog:
image: mailhog/mailhog
profiles: ["alat", "dev"]
worker:
build: .
command: celery -A tugas worker
profiles: ["pekerja"]
docker compose up # hanya api & db
docker compose --profile alat up # + pgadmin & mailhog
docker compose --profile "*" up # semuanya
depends_on dengan Kondisi — Menghentikan Balapan Startup
🚫 depends_on biasa hanya menunggu kontainer MENYALA
Ia tidak menunggu layanan di dalamnya siap melayani. Kontainer PostgreSQL menyala dalam sepersekian detik, tetapi butuh beberapa detik lagi sebelum menerima koneksi. Aplikasi Anda akan gagal terhubung lalu mati — inilah penyebab masalah "kadang jalan, kadang tidak" yang sangat sering ditemui.
Ia tidak menunggu layanan di dalamnya siap melayani. Kontainer PostgreSQL menyala dalam sepersekian detik, tetapi butuh beberapa detik lagi sebelum menerima koneksi. Aplikasi Anda akan gagal terhubung lalu mati — inilah penyebab masalah "kadang jalan, kadang tidak" yang sangat sering ditemui.
services:
db:
image: postgres:17-alpine
environment:
POSTGRES_PASSWORD: rahasia
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s
redis:
image: redis:8-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
retries: 5
migrasi:
build: .
command: alembic upgrade head
depends_on:
db: { condition: service_healthy }
api:
build: .
depends_on:
db: { condition: service_healthy }
redis: { condition: service_healthy }
migrasi: { condition: service_completed_successfully }
| Kondisi | Menunggu sampai |
|---|---|
service_started | Kontainer menyala (perilaku bawaan) |
service_healthy | Health check melaporkan sehat |
service_completed_successfully | Kontainer selesai dengan kode keluar 0 |
Berkas Berlapis untuk Dev dan Produksi
# compose.yaml — dasar bersama
services:
api:
image: registry.contoh.com/app:${TAG:-latest}
environment:
DATABASE_URL: postgresql://postgres:rahasia@db:5432/app
depends_on:
db: { condition: service_healthy }
db:
image: postgres:17-alpine
volumes: [data_db:/var/lib/postgresql/data]
volumes:
data_db:
# compose.override.yaml — otomatis dipakai saat pengembangan
services:
api:
build: .
ports: ["8000:8000"]
environment:
DEBUG: "true"
develop:
watch:
- action: sync
path: ./app
target: /app/app
# compose.prod.yaml — dipanggil eksplisit
services:
api:
restart: unless-stopped
deploy:
replicas: 3
resources:
limits: { memory: 512M }
logging:
driver: json-file
options: { max-size: "10m", max-file: "3" }
docker compose up # dasar + override otomatis
docker compose -f compose.yaml -f compose.prod.yaml up -d
Kesalahan Umum
⚠️ Rotasi log sering terlupakan
Tanpa opsi
Tanpa opsi
logging, berkas log kontainer tumbuh tanpa batas sampai memenuhi disk server. Ini penyebab pemadaman yang membingungkan karena gejalanya muncul berbulan-bulan setelah deploy. Selalu setel max-size dan max-file.
# ❌ Rahasia langsung di berkas yang masuk git
environment:
DB_PASSWORD: rahasia123
# ✅ Dari berkas .env yang diabaikan git
environment:
DB_PASSWORD: ${DB_PASSWORD:?wajib diisi}
# ✅ Atau memakai secret Compose
secrets:
db_password:
file: ./rahasia/db_password.txt
services:
api:
secrets: [db_password]
environment:
DB_PASSWORD_FILE: /run/secrets/db_password
# Perintah yang berguna
docker compose config # tampilkan hasil gabungan akhir
docker compose ps --format json
docker compose logs -f --tail=100 api
docker compose exec api sh
docker compose down -v # ⚠️ -v juga MENGHAPUS volume beserta datanya