Aplikasi Node.js di produksi jarang berdiri sendirian. Aplikasi tugas kita butuh database; mungkin juga proxy terbalik di depannya, dan pekerja latar belakang di belakangnya. Menjalankan tiap komponen dengan docker run terpisah bisa saja dilakukan, tetapi daftar flagnya panjang dan harus diingat urutannya: buat jaringan dulu, nyalakan database tunggu sampai siap, baru nyalakan aplikasi dengan alamat yang benar. Docker Compose memindahkan seluruh pengaturan itu ke satu berkas YAML — lalu satu perintah menyalakan semuanya dalam urutan yang benar. Pada chapter ini kita susun aplikasi plus database dalam satu berkas deklaratif, pelajari bagaimana container saling menemukan, dan lihat siklus hidup perintahnya.
Apa yang Dikelola Compose #
Bandingkan dua cara menjalankan pasangan aplikasi-database:
| Aspek | docker run manual | Docker Compose |
|---|---|---|
| Definisi | tersebar di riwayat shell | satu berkas docker-compose.yml di repo |
| Jaringan antar-container | dibuat dan disambungkan manual | satu jaringan default untuk semua service |
| Urutan penyalaan | kita menunggu manual | depends_on dengan kondisi kesehatan |
| Data database | flag -v yang harus konsisten | volume bernama dideklarasikan sekali |
| Menyalakan semuanya | ulangi seluruh perintah | docker compose up -d |
Selain keringkasan, perbedaan terbesarnya bersifat sosial: berkas compose terbaca seperti dokumentasi. Rekan tim yang membuka repo langsung tahu komponen apa saja yang dibutuhkan aplikasi dan bagaimana keduanya tersambung.
Berkas docker-compose.yml #
Aplikasi contoh kita memakai PostgreSQL — driver dan pola koneksinya sudah dibahas di chapter Koneksi PostgreSQL dengan pg. Berkas berikut mendefinisikan keduanya:
services:
app:
build: .
ports:
- "3000:3000"
environment:
PORT: 3000
DATABASE_URL: postgres://tugas:rahasia-contoh@db:5432/tugas
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: tugas
POSTGRES_PASSWORD: rahasia-contoh
POSTGRES_DB: tugas
volumes:
- data-db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U tugas"]
interval: 5s
retries: 5
start_period: 5s
volumes:
data-db:Mari kita bedah bagian-bagiannya:
services: setiap kunci di bawahnya adalah satu service — unit yang akan dijalankan sebagai container. Di sini adaappdandb; nama inilah yang nanti dipakai sebagai alamat jaringan.build: .: serviceappdibangun dariDockerfiledi folder yang sama — persis Dockerfile Chapter Docker untuk Node.js. Servicedbmemakaiimagesaja karena tidak perlu dibangun; PostgreSQL resmi tinggal dipakai.ports: memetakan port komputer ke port container, sama seperti flag-p— hanya service yang perlu diakses dari luar yang memetakan port; database cukup hidup di jaringan internal.environment: menyuntikkan environment variable ke container. Perhatikan host padaDATABASE_URL: namanyadb, bukanlocalhost— penjelasannya di bagian berikutnya.depends_ondengancondition: service_healthy: aplikasi menunggu sampai database dinyatakan sehat, bukan sekadar menyala. Tanpa kondisi ini,appbisa terbangun saatdbbaru berjalan tetapi belum siap menerima koneksi — aplikasi kita sendiri yang harus mengulang koneksi berkali-kali.volumes: data-db:...: data PostgreSQL disimpan pada volume bernamadata-dbsehingga data bertahan ketika container database dibuat ulang. Deklarasivolumes:di akar berkas mendaftarkan volume tersebut.healthcheck: cara Compose menilai “sehat” untuk servicedb— perintahpg_isreadydiperiksa setiapinterval, boleh gagal sebanyakretries, denganstart_periodsebagai masa penyesuaian awal.restart: unless-stopped: kebijakan penyalaan ulang — container yang berhenti karena galat dihidupkan kembali, tetapi tidak dipaksa bila memang dihentikan secara sengaja; perilaku yang sejalan dengan semangat process manager pada Chapter Process Manager dengan PM2.
Container Saling Menemukan Lewat Nama Service #
Semua service dalam satu berkas compose otomatis bergabung ke satu jaringan yang sama, dan setiap container dapat ditemukan oleh container lain memakai nama servicenya. Itulah alamat DATABASE_URL di atas menunjuk ke host db: dari dalam jaringan compose, nama tersebut dirujuk ke container database — sedangkan localhost di dalam container app berarti container app itu sendiri, tempat tidak ada PostgreSQL. Perilaku jaringan default ini dijelaskan pada panduan jaringan Docker Compose
, dan seluruh kunci berkas compose — termasuk env_file, depends_on, dan healthcheck — terdokumentasi di referensi berkas compose
.
Siklus Hidup Perintah #
Empat perintah menutup siklus hidup seluruh stack:
docker compose up -d # bangun image bila perlu, lalu nyalakan semua service
docker compose ps # status seluruh service
docker compose logs -f app # ikuti log aplikasi
docker compose down # hentikan dan hapus seluruh container serta jaringanPerintah up -d membangun image app bila belum ada atau bila Dockerfile berubah, membuat jaringan, menyalakan db, menunggu healthcheck-nya lulus, baru menyalakan app — seluruh urutan yang tadinya kita kerjakan manual. Opsi -f pada logs mengikuti aliran log secara langsung; tambahkan nama service untuk memfilter salah satunya. Perintah down membersihkan semuanya, tetapi volume data-db sengaja dipertahankan agar data bertahan — tambahkan flag -v pada down bila kita memang ingin menghapus datanya juga.
Kapan Compose Cukup #
Compose bersinar di tiga tempat. Pertama, lingkungan pengembangan: satu perintah menghadirkan aplikasi beserta database tanpa memasang apa pun di komputer selain Docker. Kedua, server kecil hingga menengah: satu berkas yang mudah dibaca seringkali lebih sehat daripada orkestrasi yang berlebihan. Ketiga, pipeline CI — bab berikutnya akan menunjukkan pipeline GitHub Actions yang memakai Compose untuk menyediakan database uji. Untuk klaster besar lintas mesin, kebutuhannya bergeser ke orchestrator seperti Kubernetes; batas praktisnya bukan angka container, melainkan saat kita mulai menjalankan banyak mesin.
Pengelolaan proses, pengemasan, dan orkestrasi kini lengkap. Dua chapter berikutnya menutup kebutuhan operasional yang tersisa: membuat aplikasi yang bisa dipantau (logging dan metrik) dan aplikasi yang berhenti dengan sopan (graceful shutdown).