Template Dockerfile dari chapter sebelumnya menghasilkan satu image yang rapi, tetapi aplikasi nyata jarang berdiri sendiri: ada database yang harus sehat sebelum aplikasi menyala, cache yang hidup di network terpisah, dan alat debug yang hanya boleh muncul saat dipanggil. Semua keputusan itu hidup di satu berkas compose.yaml, dan seperti Dockerfile, berkas ini juga punya pola berulang yang bisa dijadikan titik berangkat. Chapter ini menyediakan satu template lengkap siap salin — aplikasi, PostgreSQL, Redis, dan shell debug dalam topologi dua network — lalu menutupnya dengan tabel sebelas perintah harian dan lima belas kunci yang menutup hampir seluruh kebutuhan sehari-hari.

Template compose.yaml Lengkap #

Template berikut mengikuti seluruh konvensi Course: tanpa kunci version: yang sudah obsolete, password datang dari interpolasi .env, database diberi healthcheck pg_isready, aplikasi menunggu dengan condition: service_healthy, dan akses database dibatasi di network backend.

yaml
name: katalog                       # nama project: menjadi prefix container dan network

services:
  web:                              # aplikasi utama, dibangun dari Dockerfile lokal
    build: .                        # context build: folder tempat compose.yaml berada
    restart: unless-stopped         # bangkit sendiri pasca-restart daemon, patuh pada stop manual
    ports:
      - "8080:3000"                 # port host 8080 meneruskan ke port container 3000
    environment:
      DATABASE_URL: postgres://katalog:${DB_PASSWORD:?}@db:5432/katalog
      REDIS_URL: redis://cache:6379   # alamat service lain cukup memakai nama DNS Compose
    depends_on:
      db:
        condition: service_healthy  # tunggu db benar-benar sehat, bukan sekadar menyala
      cache:
        condition: service_started  # cache cukup dianggap siap begitu container start
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/healthz"]
      interval: 30s                 # jeda antar probe
      timeout: 5s                   # batas waktu satu probe sebelum dianggap gagal
      retries: 3                    # jumlah kegagalan berturut-turut sebelum unhealthy
    networks:
      - frontend                    # zona yang boleh diakses proxy atau dunia luar
      - backend                     # jembatan menuju db dan cache

  db:
    image: postgres:18-alpine       # image resmi PostgreSQL 18 berbasis Alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: katalog
      POSTGRES_PASSWORD: ${DB_PASSWORD:?}   # :? = wajib terisi, Compose gagal cepat bila kosong
      POSTGRES_DB: katalog
    volumes:
      - db-data:/var/lib/postgresql/data    # data bertahan melewati down dan up ulang
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U katalog -d katalog"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend                     # hanya service pada network ini yang bisa menghubungi db

  cache:
    image: redis:7-alpine           # Redis 7 stabil berbasis Alpine
    restart: unless-stopped
    command: redis-server --appendonly yes   # timpa CMD image: aktifkan persistensi AOF
    volumes:
      - cache-data:/data
    networks:
      - backend

  debug:                            # shell darurat untuk memeriksa network backend
    image: busybox                  # image utilitas kecil untuk berbagai alat darurat
    profiles: ["debug"]             # hanya dibuat bila --profile debug aktif
    command: sleep infinity         # tidur selamanya agar bisa di-exec berkali-kali
    networks:
      - backend

volumes:
  db-data:                          # volume bernama, dikelola sepenuhnya oleh Docker
  cache-data:

networks:
  frontend:                         # zona publik: reverse proxy bertemu aplikasi
  backend:                          # zona privat: aplikasi, database, dan cache saja

Mari kita telaah keputusan-keputusan penting yang tertanam di template di atas:

  1. name: katalog — nama project menentukan prefix seluruh resource (katalog-web-1, katalog-db-1, network katalog_default), sehingga satu mesin bisa memuat beberapa stack tanpa bertabrakan nama.
  2. ${DB_PASSWORD:?} — tanda :? membuat Compose menolak menjalankan stack bila variabel kosong; kesalahan konfigurasi ketahuan sebelum container dibuat, bukan setelah aplikasi crash.
  3. condition: service_healthy — urutan start menjadi urutan kesiapan: web baru dibuat setelah healthcheck db hijau, pola yang kita bedah tuntas di chapter depends_on dan Startup Order.
  4. Pemisahan frontend dan backend — db dan cache tidak punya ports:, sehingga tidak satu pun port database terekspos ke host; hanya web yang menerbitkan port.
  5. profiles: ["debug"] — service debug tidak ikut up biasa; ia hadir hanya saat dipanggil dengan docker compose run --rm debug sh atau --profile debug.

Sebelas Perintah Harian #

Seluruh perintah memakai bentuk plugin docker compose dengan spasi. Dua baris terakhir menghapus resource, jadi baca catatannya sebelum menekan enter.

PerintahFungsi
docker compose up -dmenjalankan seluruh stack di background
docker compose up -d --buildmembangun ulang image lalu menjalankan stack
docker compose psmelihat status seluruh service project aktif
docker compose logs -f webmengikuti log satu service secara realtime
docker compose exec web shmembuka shell di dalam service yang sedang berjalan
docker compose run --rm debug shmenjalankan container sekali pakai lalu menghapusnya
docker compose watchmengaktifkan aturan develop.watch untuk sinkron dan rebuild
docker compose configmemvalidasi berkas dan menampilkan hasil interpolasi
docker compose stopmenghentikan service tanpa menghapus container
docker compose downmenghapus container dan network project
docker compose down -vWARNING: turut menghapus volume bernama — data database hilang permanen

Lima Belas Kunci Paling Sering #

Tabel berikut merangkum kunci yang menutup mayoritas compose.yaml di dunia nyata; sisanya bisa dicari di referensi resmi saat kasusnya benar-benar muncul.

KunciLevelKegunaan
namerootnama project sekaligus prefix resource
servicesrootwadah seluruh definisi service
buildservicemembangun image dari Dockerfile, bukan menarik dari registry
imageserviceimage yang ditarik bila tidak membangun sendiri
portsservicemenerbitkan port ke host, format "host:container"
environmentservicevariabel lingkungan langsung di dalam berkas
env_fileservicememuat variabel dari berkas terpisah seperti .env
commandservicemenimpa CMD default image
depends_onservicemengatur urutan start dan kondisi kesiapan
healthcheckserviceprobe kesehatan yang menentukan status service
restartservicekebijakan bangkit: no, on-failure, always, unless-stopped
volumesservicemount volume bernama atau bind mount ke service
networksservice dan rootkeanggotaan network dan definisinya
profilesservicemengelompokkan service yang hanya aktif bila dipanggil
developserviceblok watch untuk sinkronisasi saat pengembangan

Template dan tabel ini membuat compose.yaml cepat ditulis, tetapi kecepatan menulis bukan tujuan akhir: Dockerfile yang dirawat bertahun-tahun oleh banyak orang menuntut konsistensi — huruf besar instruksi, komentar per blok, pin versi, dan .dockerignore yang sama di setiap repository. Konsistensi semacam itu hanya lahir dari kesepakatan tertulis. Chapter berikutnya merumuskan kesepakatan itu sebagai Konvensi Penulisan Dockerfile yang bisa diadopsi langsung oleh tim kita.

Referensi #