Tampilan
Kenapa penting
Aplikasi backend jarang berdiri sendiri: order-service butuh PostgreSQL, cache Redis, mungkin juga Kafka. Memasang semua itu langsung di laptop membuat versi berbeda antar-anggota tim dan onboarding memakan waktu sehari. Docker Compose mendeskripsikan seluruh lingkungan dalam satu file compose.yaml yang di-commit bersama kode, sehingga siapa pun cukup menjalankan docker compose up -d. Di tempat kerja, Compose dipakai untuk development lokal, demo, dan menjalankan dependency saat debugging — dan Spring Boot punya dukungan bawaan untuknya.
Konsep inti
Anatomi compose.yaml
File Compose berisi daftar services (satu service = satu atau beberapa container dari image yang sama), plus volumes dan networks yang dipakai bersama. Nama file standar adalah compose.yaml; field version di bagian atas sudah usang dan tidak perlu ditulis.
yaml
services:
postgres:
image: postgres:17
environment:
POSTGRES_DB: orders
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
ports:
- "15432:5432" # host:container
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:| Field | Fungsi |
|---|---|
image / build | image yang dipakai, atau folder berisi Dockerfile untuk dibangun |
ports | memetakan port host → port container ("HOST:CONTAINER") |
environment | variabel lingkungan untuk container |
volumes | named volume atau bind mount ke path di container |
networks | network yang diikuti service (default: satu network untuk seluruh project) |
depends_on | urutan start dan syarat kesiapan service lain |
healthcheck | perintah untuk menilai apakah container sehat |
Network dan nama service
Compose otomatis membuat satu network untuk project. Setiap service bisa dipanggil lewat nama service-nya sebagai hostname, memakai port container. Dari container app, database ada di postgres:5432 — bukan localhost. Bagian ports hanya dibutuhkan agar host (IDE, DBeaver, psql di laptop) bisa mengakses service.
Kamu bisa memisahkan network bila perlu, mis. database hanya bisa dijangkau backend:
yaml
services:
app:
networks: [frontend, backend]
postgres:
networks: [backend]
networks:
frontend:
backend:depends_on + healthcheck
depends_on bentuk daftar hanya menjamin container dependensi dijalankan lebih dulu. PostgreSQL butuh beberapa detik untuk inisialisasi, jadi aplikasi yang langsung konek akan gagal. Solusinya: definisikan healthcheck dan tunggu status healthy.
yaml
services:
postgres:
image: postgres:17
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d orders"]
interval: 5s
timeout: 3s
retries: 10
redis:
image: redis:7
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
app:
build: .
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthyKondisi lain: service_started (setara bentuk daftar) dan service_completed_successfully (untuk job sekali jalan seperti migrasi).
Data persisten
Layer tulis container hilang saat container dihapus. Simpan data database di named volume (dikelola Docker, tetap ada setelah down) atau bind mount (folder host, cocok untuk file konfigurasi atau skrip inisialisasi).
yaml
services:
postgres:
volumes:
- pgdata:/var/lib/postgresql/data # named volume: data persisten
- ./db/init:/docker-entrypoint-initdb.d:ro # bind mount: skrip SQL awal, read-onlyPostgreSQL 18 mengubah path data
Image resmi postgres:18 memindahkan lokasi data default (variabel PGDATA) ke subfolder versi di bawah /var/lib/postgresql. Bila kamu naik ke 18, sesuaikan mount volume dengan dokumentasi image — contoh di bab ini memakai postgres:17.
Perintah sehari-hari
bash
docker compose up -d # jalankan semua service di background
docker compose ps # status & health tiap service
docker compose logs -f app # ikuti log satu service
docker compose exec postgres psql -U app -d orders # masuk ke container
docker compose down # hentikan & hapus container + network (volume tetap)
docker compose down -v # ... sekaligus hapus named volume (data hilang)
docker compose config # validasi & tampilkan konfigurasi akhirdocker compose up -d --wait menunggu sampai semua service running/healthy — berguna di skrip dan CI.
Spring Boot Docker Compose support
Spring Boot bisa mengelola Compose untukmu saat development. Tambahkan dependency berikut:
xml
<!-- Potongan pom.xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-docker-compose</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>Saat aplikasi dijalankan, Boot mencari compose.yaml di folder kerja, menjalankan docker compose up, menunggu container siap, lalu membuat service connection untuk image yang dikenalnya (antara lain postgres dan redis). Kamu tidak perlu menulis spring.datasource.url untuk lokal — host, port acak, dan kredensial dibaca dari container. Saat aplikasi berhenti, container ikut dihentikan (spring.docker.compose.lifecycle-management=start-and-stop, default). Pilihan lain: start-only atau none. Secara default fitur ini dilewati saat test; untuk test, pakai Testcontainers seperti di bab sebelumnya.
Contoh di dunia backend
Stack lokal order-service: aplikasi Spring Boot (dibangun dari Dockerfile bab sebelumnya), PostgreSQL untuk data pesanan, Redis untuk cache katalog.
yaml
# compose.yaml — Potongan stack lokal order-service
name: order-service
services:
app:
build: .
ports:
- "8080:8080"
environment:
SPRING_PROFILES_ACTIVE: local
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/orders
SPRING_DATASOURCE_USERNAME: app
SPRING_DATASOURCE_PASSWORD: secret
SPRING_DATA_REDIS_HOST: redis
JAVA_TOOL_OPTIONS: -XX:MaxRAMPercentage=75
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks: [backend]
postgres:
image: postgres:17
environment:
POSTGRES_DB: orders
POSTGRES_USER: app
POSTGRES_PASSWORD: secret # kredensial dummy khusus lokal
ports:
- "15432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d orders"]
interval: 5s
timeout: 3s
retries: 10
networks: [backend]
redis:
image: redis:7
ports:
- "16379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
networks: [backend]
volumes:
pgdata:
networks:
backend:Alur kerja harian: docker compose up -d --build setelah menarik perubahan, docker compose logs -f app saat debugging, dan docker compose down di akhir hari. Bila skema rusak karena eksperimen migrasi Flyway, docker compose down -v memberi database bersih.
Sering juga tim tidak memasukkan app ke Compose: hanya PostgreSQL dan Redis yang dijalankan (lewat Spring Boot Docker Compose support), sementara aplikasi dijalankan dari IDE agar debugger dan hot reload tetap nyaman.
Dev vs production
Compose ideal untuk lingkungan lokal, demo, dan server tunggal sederhana. Production biasanya memakai orkestrator (Kubernetes, ECS) yang menangani scaling, rolling update, dan self-healing lintas mesin. Kredensial di file Compose lokal boleh dummy; secret production tidak pernah ditulis di repo.
Pertanyaan interview
1. Apa beda depends_on biasa dengan condition: service_healthy?
Bentuk biasa hanya mengatur urutan start: container dependensi dijalankan lebih dulu, tetapi belum tentu siap. Dengan service_healthy, Compose menunggu healthcheck service itu lulus — mis. pg_isready sukses — sebelum menjalankan service yang bergantung padanya.
2. Kenapa aplikasi di container tidak bisa memakai localhost untuk konek ke database di Compose?
Setiap container punya network namespace sendiri, jadi localhost menunjuk container itu sendiri. Di network Compose, service dipanggil lewat nama service dan port container, mis. postgres:5432. Port mapping ports hanya untuk akses dari host.
3. Bagaimana menjaga data database tetap ada saat container dibuat ulang?
Simpan direktori data di named volume. Volume hidup terpisah dari container, sehingga docker compose down lalu up tetap memakai data lama. Data baru hilang bila volume dihapus, mis. dengan docker compose down -v.
Jebakan umum
- Mengandalkan
depends_ontanpahealthcheck— aplikasi start sebelum database siap dan gagal konek. - Memakai
localhostdi URL JDBC dari dalam container — seharusnya nama service (postgres). - Menjalankan
docker compose down -vtanpa sadar — named volume terhapus beserta seluruh data lokal. - Lupa
--buildsetelah mengubah kode — Compose menjalankan image lama. - Menulis secret production di
compose.yamlyang di-commit. - Bentrok port host (mis. PostgreSQL lokal sudah memakai 5432) — petakan ke port host lain seperti
15432.
Ringkasan
compose.yamlmendeskripsikan seluruh lingkungan lokal: services, ports, environment, volumes, networks.- Antar-service saling memanggil lewat nama service dan port container;
portsuntuk akses dari host. - Gunakan
healthcheck+depends_ondengancondition: service_healthyagar urutan start benar. - Named volume menyimpan data persisten;
down -vmenghapusnya. spring-boot-docker-composemenyalakan service dan membuat service connection otomatis saat development.- Compose untuk dev/demo; production memakai orkestrator dan secret manager.