Lewati ke isi

Server & Infrastruktur

Cara Menyiapkan Docker Compose untuk Staging dan Produksi

Satu set file Compose untuk staging dan produksi: file dasar, file per lingkungan, .env terpisah, nama proyek, dan cara mengecek hasil gabungannya.

Terbit 5 menit baca

Jawaban singkat

Simpan pengaturan yang sama di compose.yaml, lalu taruh perbedaan staging dan produksi di file terpisah seperti compose.staging.yaml dan compose.prod.yaml. Jalankan dengan beberapa opsi -f, file .env berbeda, dan nama proyek berbeda, lalu cek hasil gabungan dengan docker compose config.

Daftar isi
  1. Struktur file seperti apa yang disarankan?
  2. Isi file dasar dan file per lingkungan
  3. Bagaimana menjalankan setiap lingkungan?
  4. Bagaimana memastikan hasil gabungannya benar?
  5. Bagaimana dengan service yang hanya dipakai di staging?
  6. Kebiasaan yang membuat produksi lebih tenang
  7. Pertanyaan yang sering diajukan

Cara paling rapi menyiapkan Docker Compose untuk staging dan produksi adalah satu file dasar yang berisi semua yang sama, ditambah satu file kecil per lingkungan yang hanya berisi perbedaannya. Compose menggabungkan file-file itu saat dijalankan.

Kenapa ini penting? Banyak tim memulai dengan menyalin docker-compose.yml menjadi dua file terpisah untuk staging dan produksi. Beberapa bulan kemudian, kedua file sudah berbeda di banyak tempat yang tidak disengaja, dan bug yang tidak muncul di staging tiba-tiba muncul di produksi. Dengan file dasar bersama, perbedaan kedua lingkungan menjadi sedikit, jelas, dan bisa ditinjau.

Struktur file seperti apa yang disarankan?

Contoh untuk aplikasi web dengan database:

proyek/
  compose.yaml           # pengaturan bersama
  compose.override.yaml  # khusus laptop developer (dimuat otomatis)
  compose.staging.yaml   # perbedaan staging
  compose.prod.yaml      # perbedaan produksi
  .env.staging
  .env.prod

Dokumentasi Docker menjelaskan bahwa bila kamu menjalankan docker compose up tanpa opsi -f, Compose membaca compose.yaml dan otomatis menggabungkan compose.override.yaml bila ada. Karena itu file override cocok untuk pengaturan laptop developer, seperti memasang folder kode sebagai volume. Di server, kamu selalu menyebut file secara eksplisit sehingga override itu tidak ikut termuat.

Isi file dasar dan file per lingkungan

compose.yaml berisi hal yang sama di semua tempat:

services:
  app:
    image: registry.contoh.com/tim/app:${APP_TAG:-latest}
    environment:
      DATABASE_URL: postgres://postgres:${DB_PASSWORD}@db:5432/app
    depends_on:
      - db
  db:
    image: postgres:17
    environment:
      POSTGRES_DB: app
      POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD wajib diisi}
    volumes:
      - dbdata:/var/lib/postgresql/data

volumes:
  dbdata:

compose.prod.yaml hanya berisi yang berbeda untuk produksi:

services:
  app:
    restart: unless-stopped
    ports:
      - "127.0.0.1:8000:8000"
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"
  db:
    restart: unless-stopped

compose.staging.yaml mirip, tapi misalnya memakai port lain dan tag image yang lebih baru.

Perhatikan port 127.0.0.1:8000:8000. Port hanya dibuka untuk localhost, lalu Nginx di host yang meneruskan trafik dari luar. Kalau ditulis 8000:8000 saja, Docker membuka port ke semua alamat dan aturan iptables yang dibuat Docker bisa melewati UFW. Penjelasannya ada di cara mengamankan Docker agar port tidak bocor.

Sintaks ${DB_PASSWORD:?pesan} membuat Compose berhenti dengan pesan error bila variabel itu kosong. Ini mencegah database produksi terbuat dengan password kosong gara-gara file .env lupa disalin.

Bagaimana menjalankan setiap lingkungan?

Produksi:

docker compose -p app-prod --env-file .env.prod \
  -f compose.yaml -f compose.prod.yaml up -d

Staging di server yang sama:

docker compose -p app-staging --env-file .env.staging \
  -f compose.yaml -f compose.staging.yaml up -d

Tiga hal yang perlu diperhatikan:

  • Urutan file penting. File yang disebut belakangan menimpa atau menambah pengaturan file sebelumnya.
  • Nama proyek (-p) wajib berbeda bila staging dan produksi berada di server yang sama. Nama proyek menjadi awalan nama container, jaringan, dan volume. Tanpa itu, kedua lingkungan bisa saling menimpa, termasuk volume database.
  • --env-file mengisi variabel ${...} di file Compose. env_file: di dalam service mengisi variabel di dalam container. Keduanya berbeda, dan sering tertukar.

Supaya tidak salah ketik, simpan perintah di skrip kecil seperti deploy-prod.sh, atau isi COMPOSE_FILE dan COMPOSE_PROJECT_NAME di file .env di folder masing-masing lingkungan.

Bagaimana memastikan hasil gabungannya benar?

Sebelum menjalankan up, lihat konfigurasi akhir setelah digabung:

docker compose -p app-prod --env-file .env.prod \
  -f compose.yaml -f compose.prod.yaml config

Perintah ini menampilkan YAML lengkap dengan semua variabel sudah terisi. Di sinilah kamu bisa memastikan port, tag image, dan pengaturan restart sesuai harapan. Hati-hati, hasilnya juga menampilkan password dari file env, jadi jangan disalin ke chat atau tiket.

Perlu diingat bagaimana penggabungan bekerja. Untuk nilai tunggal seperti image atau restart, file belakangan menggantikan nilai sebelumnya. Untuk daftar seperti ports, isi digabungkan, sehingga port dari file dasar dan file produksi ikut dua-duanya. Karena itu, taruh ports hanya di file per lingkungan, jangan di file dasar.

PengaturanTaruh di file dasarTaruh di file lingkungan
Daftar service dan imageYaHanya tag yang berbeda
Volume dataYaTidak
Port yang dibukaTidakYa
restart, batas log, batas CPU dan RAMTidakYa
Password dan tokenTidak, pakai variabelIsi lewat file .env yang tidak masuk Git

Bagaimana dengan service yang hanya dipakai di staging?

Kadang ada service yang hanya dibutuhkan di staging, misalnya penangkap email palsu seperti Mailpit, atau alat admin database. Compose punya fitur profiles:

services:
  mailpit:
    image: axllent/mailpit
    profiles: [staging]

Service dengan profil tidak dijalankan kecuali profilnya diaktifkan dengan --profile staging. Jadi produksi tidak pernah ikut menjalankannya meski file dasarnya sama.

Kebiasaan yang membuat produksi lebih tenang

Pakai tag image yang jelas, misalnya nomor versi atau hash commit, bukan latest, agar staging dan produksi bisa dipastikan memakai image yang sama. Simpan file .env.prod hanya di server, tidak di repo. Batasi CPU dan RAM container di file produksi seperti dijelaskan di panduan membatasi CPU dan RAM container. Dan sebelum memperbarui container, pahami dulu di mana datanya disimpan supaya volume database tidak ikut terhapus.

Untuk memperbarui produksi ke versi baru, ubah APP_TAG di .env.prod, lalu jalankan pull dan up -d dengan opsi -p, --env-file, dan -f yang sama seperti saat pertama menjalankan. Compose hanya membuat ulang container yang konfigurasinya atau image-nya berubah, sedangkan volume bernama seperti dbdata tetap dipakai. Hindari docker compose down -v di produksi, karena opsi -v ikut menghapus volume beserta isi database.

Pertanyaan yang sering diajukan

Apakah staging dan produksi boleh di VPS yang sama?

Boleh untuk tim kecil, asal nama proyek, port, dan volume berbeda. Tetapi beban di staging tetap memakai RAM dan CPU produksi, jadi untuk aplikasi sibuk lebih aman dipisah ke server lain.

Apa bedanya docker-compose dan docker compose?

docker-compose dengan tanda hubung adalah versi lama yang berdiri sendiri. docker compose (tanpa tanda hubung) adalah plugin Compose versi 2 yang kini menjadi cara utama dalam dokumentasi Docker.

Perlukah baris version di atas file Compose?

Dokumentasi Compose sekarang menyebut elemen version sudah usang dan hanya diabaikan. Kamu boleh menghapusnya.

Sumber & referensi

Baca juga