depends_on dan Healthcheck

Urutan startup yang benar dengan condition: service_healthy dan definisi healthcheck untuk basis data.

Daftar isi

Urutan mulai antar service, yaitu kelompok container yang dideskripsikan compose.yaml, menentukan apakah aplikasi dapat tersambung ke basis datanya sejak detik pertama. Topik ini membahas kunci depends_on, yaitu pengatur urutan mulai pada compose.yaml, beserta healthcheck, yaitu pemeriksaan berkala yang menguji apakah sebuah service benar-benar siap melayani. Masalah urutan yang muncul pada basis data PostgreSQL, solusinya dengan condition: service_healthy, dan status kesehatan yang terlihat saat proyek berjalan dibahas satu per satu. Proyek (project) berarti kesatuan container dari satu compose.yaml. Setelah membacanya, service web dapat disuruh menunggu sampai basis data siap menerima koneksi, bukan sekadar sampai containernya hidup.

Masalah urutan startup#

Kunci depends_on menyatakan ketergantungan antar service. Dengan depends_on: [db] pada service web, Compose membuat dan memulai container db terlebih dahulu sebelum container web. Bentuk bawaan ini hanya menunggu container db mulai berjalan, dan itulah sumber masalahnya, karena mulai berjalan belum berarti siap melayani.

Basis data PostgreSQL menjalankan inisialisasi pada container pertama, yaitu membuat berkas basis data baru melalui proses initdb sebelum menerima koneksi apa pun. Tahap ini memakan waktu beberapa detik, dan selama tahap itu upaya koneksi dari aplikasi ditolak. Aplikasi catatan yang dimulai serentak dengan container basis datanya pun dapat menemui error koneksi pada awal jalan, kemudian berhasil pada percobaan berikutnya setelah inisialisasi selesai. Perilaku yang kadang berhasil dan kadang gagal seperti ini sulit didiagnosis, sehingga urutan startup perlu ditegakkan secara eksplisit.

Healthcheck pada service postgres#

Healthcheck adalah pemeriksaan yang dijalankan Docker di dalam container secara berkala, dan hasilnya menentukan status kesehatan service. Pada service db, pemeriksaan yang tepat adalah pg_isready, yaitu perintah bawaan image PostgreSQL yang menguji apakah server sudah siap menerima koneksi. Perintah ini ringan karena tidak membuka koneksi basis data penuh, sehingga aman diulang setiap beberapa detik.

yaml compose.yaml
services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: postgres://postgres:rahasia-db@db:5432/catatan
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:18-alpine
    environment:
      POSTGRES_PASSWORD: rahasia-db
      POSTGRES_DB: catatan
    volumes:
      - catatan-data:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

volumes:
  catatan-data:

Kunci test memuat perintahnya, dengan bentuk CMD-SHELL yang mengeksekusinya melalui shell di dalam container. Kunci interval: 5s mengulang pemeriksaan setiap lima detik, timeout: 3s menyatakan batas tunggu satu pemeriksaan, dan retries: 5 menetapkan jumlah kegagalan berturut-turut sebelum service ditandai tidak sehat. Kunci start_period: 10s memberi masa tenggang sepuluh detik di awal, yaitu waktu ketika kegagalan pemeriksaan masih dianggap wajar dan belum dihitung terhadap retries. Dengan masa tenggang tersebut, proses initdb yang panjang tidak langsung menjatuhkan status service. Status service diawali sebagai starting dan berubah menjadi healthy begitu satu pemeriksaan berhasil, sedangkan lima kegagalan berturut-turut setelah masa tenggang menjatuhkannya menjadi unhealthy.

Tiga nilai condition pada depends_on#

Kondisi service_healthy mengubah makna depends_on: Compose menahan container web sampai healthcheck db menandai service sebagai sehat. Sejak titik itu, aplikasi mulai berjalan ketika basis data sudah benar-benar menerima koneksi, dan error koneksi pada awal jalan hilang karena sebabnya sudah ditangani. Tabel berikut memuat ketiga nilai kondisi yang diterima.

Nilai conditionArtiKegunaan
service_startedContainer service sudah mulai berjalanPerilaku bawaan, cukup untuk ketergantungan tanpa urutan ketat
service_healthyHealthcheck service melaporkan sehatBasis data dan layanan yang butuh masa inisialisasi
service_completed_successfullyContainer service berjalan sampai selesai dengan kode keluar nolService sekali jalan seperti penerapan migrasi skema

Nilai service_healthy menjadi pilihan baku untuk ketergantungan pada basis data. Nilai service_completed_successfully berguna pada pola berbeda, yaitu service yang dijalankan sekali untuk menyiapkan sesuatu, misalnya menjalankan migrasi skema sebelum aplikasi dimulai. Pada pola itu, Compose baru melanjutkan service yang bergantung setelah container selesai dengan sukses. Penulisannya berupa pemetaan nama service ke kondisinya, sehingga satu service dapat bergantung pada beberapa service dengan kondisi yang berbeda-beda.

Status kesehatan yang terlihat#

Saat proyek dihidupkan, Compose mengikuti kondisi tersebut secara otomatis tanpa perintah tambahan.

bash
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# db ditunggu sampai sehat, web baru menyusul setelahnya
docker compose up -d
# status kesehatan terbaca pada daftar container proyek
docker compose ps

Perintah docker compose up -d membuat container db terlebih dahulu dan menunggu healthchecknya, lalu membuat container web setelah kondisi terpenuhi. Apabila kondisi tidak kunjung terpenuhi, container web tidak ikut dimulai, sehingga kegagalan basis data berhenti pada awal dan tidak menular ke aplikasi. Perintah docker compose ps menampilkan baris untuk kedua container, dan kolom statusnya memuat keterangan kesehatan: db tampak (health: starting) selama masa awal, kemudian (healthy) setelah pemeriksaan pertama berhasil. Status tersebut berasal dari healthcheck, sehingga keberhasilan pengaturan urutan dapat diverifikasi dengan mata tanpa membaca log sama sekali.

Status kesehatan juga dapat dibaca lebih rinci pada docker inspect, bagian State.Health yang memuat hasil setiap pemeriksaan beserta waktunya. Informasi ini berguna saat pemeriksaan tampak macet, karena alasan kegagalan tiap percobaan tercatat di sana.

Kesalahan umum#

  1. Menulis depends_on tanpa kondisi untuk basis data. Service web dimulai serentak dengan db, dan inisialisasi initdb membuat koneksi pertama ditolak tanpa pola yang pasti. Perbaikannya dengan menambahkan condition: service_healthy di bawah nama service yang dirujuk, lalu menghidupkan ulang proyek agar urutan baru diterapkan.

  2. Menguji proses, bukan kesiapan layanan. Perintah pemeriksaan yang selalu berhasil, misalnya sekadar memastikan proses ada, membuat service ditandai sehat padahal belum siap melayani. Perbaikannya dengan memakai perintah yang benar-benar menguji layanannya, seperti pg_isready untuk PostgreSQL, dan mencobanya secara manual di dalam container sebelum dipakai.

  3. Melewatkan masa tenggang pada service yang lama berinisialisasi. Tanpa start_period, kegagalan selama initdb langsung menghitung retries, sehingga db dapat ditandai tidak sehat sebelum sempat siap dan web tidak pernah dimulai. Perbaikannya dengan memberi start_period yang menutup waktu inisialisasi terburuk.

Ringkasan#

  • depends_on bawaan hanya menunggu container yang dirujuk mulai berjalan, sedangkan basis data butuh beberapa detik inisialisasi sebelum siap melayani.
  • Kunci healthcheck: pada service db memakai pg_isready -U postgres dengan interval, timeout, retries, dan start_period sebagai pengatur pemeriksaannya.
  • depends_on dengan condition: service_healthy menahan service web sampai basis data ditandai sehat, sehingga koneksi pertama tidak lagi ditolak.
  • Status kesehatan terbaca pada docker compose ps dan pada bagian State.Health hasil docker inspect.

Referensi#