Nilai konfigurasi seperti kata sandi basis data tidak ditulis langsung ke dalam image, melainkan diberikan pada saat proyek dijalankan. Proyek (project) berarti kesatuan container dari satu compose.yaml. Topik ini membahas tiga cara memberi nilai pada compose.yaml, perbedaan berkas .env dengan env_file:, berkas override yang dimuat otomatis untuk menimpa nilai bawaan, serta pengenalan secret, yaitu mekanisme penanganan data sensitif yang diteruskan sebagai berkas. Setelah membacanya, konfigurasi aplikasi catatan terpisah dari kode, dan kata sandi tidak lagi tertulis pada berkas yang dikommit.
Tiga cara memberi nilai variabel lingkungan#
Kunci environment: menuliskan pasangan kunci dan nilai langsung pada service, yaitu kelompok container yang dideskripsikan compose.yaml, dan cara ini paling sederhana untuk nilai yang tidak sensitif. Notasi ${VAR} melakukan interpolasi, yaitu penggantian variabel pada saat Compose membaca berkas, dengan nilai yang diambil dari berkas .env di direktori proyek. Kunci env_file: memuat satu berkas variabel secara utuh ke dalam container service yang menyebutnya. Ketiganya dapat dipakai bersamaan pada satu service, dan tabel berikut merangkum letak serta tujuan masing-masing.
| Cara | Letak nilai | Nilai dipakai oleh |
|---|---|---|
environment: | Langsung pada compose.yaml | Container service tersebut |
${VAR} | Berkas .env di direktori proyek | Compose pada saat membaca berkas |
env_file: | Berkas lain yang disebut pada service | Container service tersebut, dimuat utuh |
Perbedaan letak nilai menentukan perbedaan fungsinya. Nilai ${VAR} hanya berlaku di dalam Compose, sehingga berkas .env menjadi sumber interpolasi dan tidak otomatis menjadi variabel di dalam container. Sebaliknya, isi berkas yang disebut env_file: langsung menjadi variabel lingkungan container. Apabila satu kunci muncul di lebih dari satu tempat, nilai pada environment: selalu menang atas nilai dari env_file:.
Interpolasi dari berkas .env#
Berkas compose.yaml pada topik ini memakai ketiga cara sekaligus. Bagian yang berhubungan dengan lingkungan tertulis seperti berikut. Kunci lainnya seperti healthcheck, pemeriksaan kesiapan service, dan volume, penyimpanan yang dikelola Docker, mengikuti pola yang sudah dibahas pada topik depends_on dan Healthcheck.
services:
web:
build: .
ports:
- "8000:8000"
env_file:
- konfigurasi-app.env
environment:
DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD}@db:5432/catatan
depends_on:
db:
condition: service_healthy
secrets:
- kunci_jwt
db:
image: postgres:18-alpine
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
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:
secrets:
kunci_jwt:
file: kunci_jwt.txtBerkas .env menyediakan nilai yang dicari interpolasi. Compose membacanya secara otomatis karena letaknya di direktori proyek, yaitu direktori yang sama dengan compose.yaml.
# berkas .env untuk interpolasi compose.yaml, tidak dimuat ke container
POSTGRES_PASSWORD=rahasia-db
POSTGRES_DB=catatanLingkungan uji modul ini tidak memiliki Docker, tetapi langkah interpolasi dapat ditiru untuk melihat hasilnya. Skrip berikut membaca .env, mengganti setiap ${VAR} pada compose.yaml, lalu mencetak nilai environment service db dan DATABASE_URL service web setelah penggantian.
# tidak-dijalankan: skrip dijalankan melalui blok bash di bawah
import re
import yaml
def baca_env(nama_berkas):
variabel = {}
with open(nama_berkas) as berkas:
for baris in berkas:
baris = baris.strip()
if baris and not baris.startswith("#") and "=" in baris:
kunci, nilai = baris.split("=", 1)
variabel[kunci] = nilai
return variabel
variabel = baca_env(".env")
with open("compose.yaml") as berkas:
teks = berkas.read()
terinterpolasi = re.sub(
r"\$\{(\w+)\}", lambda m: variabel.get(m.group(1), m.group(0)), teks
)
konfigurasi = yaml.safe_load(terinterpolasi)
print("environment service db setelah interpolasi:")
for kunci, nilai in konfigurasi["services"]["db"]["environment"].items():
print(f" {kunci} = {nilai}")
url = konfigurasi["services"]["web"]["environment"]["DATABASE_URL"]
print(f"DATABASE_URL service web: {url}")# meniru interpolasi Compose untuk melihat hasil penggantiannya
python3 interpolasi.pyenvironment service db setelah interpolasi:
POSTGRES_PASSWORD = rahasia-db
POSTGRES_DB = catatan
DATABASE_URL service web: postgres://postgres:rahasia-db@db:5432/catatanKeluaran memperlihatkan dua bentuk penggantian sekaligus. Variabel pada environment service db terisi penuh dari .env, dan ${POSTGRES_PASSWORD} yang tersisip di tengah URL koneksi ikut tergantikan. Skrip di atas hanya meniru langkah Compose, sedangkan Compose sendiri melakukan interpolasi pada saat berkas dibaca, sebelum konfigurasi diteruskan ke daemon, proses latar yang mengeksekusi pekerjaan Docker. Konfigurasi akhir dapat diperiksa kapan saja melalui docker compose config.
env_file untuk variabel aplikasi#
Berkas yang dirujuk env_file: ditulis dengan format yang sama seperti .env, yaitu satu baris KUNCI=nilai untuk setiap variabel dan baris # sebagai komentar. Bedanya terletak pada penerima, karena isi berkas ini dimuat utuh ke dalam container web sebagai variabel lingkungan aplikasi. Kunci env_file: ditulis pada tingkat service dengan daftar berkas yang dimuat, dan lebih dari satu berkas boleh dirujuk sekaligus.
# dimuat ke container web melalui kunci env_file
APP_PORT=8000
APP_MODE=productionPemisahan berkas ini menjaga perintah dan compose.yaml tetap pendek ketika daftar variabel aplikasi memanjang. Nama berkasnya bebas dipilih karena yang berlaku adalah nama yang dirujuk, berbeda dengan .env yang letak dan namanya memang tetap. Di dalam container, nilai-nilai itu dibaca aplikasi seperti variabel lingkungan biasa, misalnya melalui os.environ pada Python. Apabila kunci yang sama juga ditulis pada environment:, nilai pada kunci itu yang menang, sehingga kasus khusus tetap dapat ditangani tanpa menyunting berkas env-nya.
Berkas override compose.override.yaml#
Berkas bernama compose.override.yaml dimuat otomatis oleh Compose setiap kali perintah compose dijalankan di direktori proyek, lalu digabungkan di atas compose.yaml. Kunci yang sama pada berkas ini menimpa nilai bawaannya, sedangkan kunci baru ikut ditambahkan. Pola yang lazim menjadikan compose.yaml memuat nilai bawaan untuk produksi, sedangkan override memuat pengaturan pengembangan di mesin lokal.
# dimuat otomatis untuk menimpa nilai bawaan saat pengembangan
services:
web:
build: .
volumes:
- .:/aplikasi
environment:
APP_MODE: debugPada contoh ini, service web mendapat bind mount, yaitu pemasangan direktori host, mesin tempat Docker berjalan, ke dalam container. Pemasangan itu mengarah ke kode sumber, dan APP_MODE: debug berlaku saat pengembangan. Nilai debug tersebut menimpa APP_MODE=production yang datang dari env_file:, karena kunci environment: selalu menang atas env_file:. Penggabungan dilakukan Compose per kunci, sehingga service yang disebut pada kedua berkas digabungkan, bukan digantikan utuh, dan kunci yang tidak disebut pada override tetap diambil dari berkas dasar. Proyek yang sama karenanya berjalan dalam mode produksi bila berkas override tidak ada, dan beralih ke mode pengembangan secara otomatis di mesin yang memiliki berkas tersebut.
Secret sebagai berkas#
Data yang paling sensitif seperti kunci penandatanganan token sebaiknya tidak melewati variabel lingkungan sama sekali, karena variabel lingkungan terbaca pada docker inspect dan tertulis pada log beberapa alat. Kunci secrets: tingkat atas memperkenalkan jalur lain: secret dinyatakan bersumber dari sebuah berkas, lalu dirujuk oleh service yang membutuhkannya. Berkas berikut memuat kunci milik aplikasi catatan.
b1f9c2e7-4a8d-4e6b-9c31-7d2f5a8e0b46Deklarasinya pada compose.yaml memakai file: kunci_jwt.txt, sedangkan service web merujuknya seperti berikut.
secrets:
- kunci_jwtPada Compose biasa, secret diteruskan sebagai berkas yang dipasang di dalam container pada jalur /run/secrets/kunci_jwt, bukan sebagai variabel lingkungan. Aplikasi membacanya sebagai berkas biasa pada saat membutuhkan, dan nilai itu tidak pernah tampil pada daftar variabel lingkungan container. Jalur pemasangannya juga hanya ada selama container berjalan, sehingga berkas secret tidak ikut tersimpan pada lapisan image.
Kesalahan umum#
Mengira berkas .env dimuat ke dalam container. Berkas itu hanya sumber interpolasi bagi Compose, sehingga aplikasi tidak melihat isinya meskipun berkasnya berada di direktori proyek. Perbaikannya dengan memakai
env_file:untuk variabel container atauenvironment:untuk kasus khusus.Menulis kata sandi langsung pada
environment:. Nilai itu ikut tersimpan pada compose.yaml yang dikommit dan terbaca padadocker inspect. Perbaikannya dengan memindahkan nilai sensitif ke .env lalu memakai interpolasi, atau kesecrets:untuk yang paling sensitif, dan memastikan berkas hasilnya tidak terkommit pula.Bingung karena perilaku compose berbeda dari berkasnya. compose.override.yaml ikut dimuat tanpa disebut pada perintah, sehingga hasil gabungannya berbeda dari isi compose.yaml saja. Perbaikannya dengan memeriksa konfigurasi akhir melalui
docker compose configsebelum menyimpulkan, karena perintah itu mencetak hasil gabungan seluruh berkas.
Ringkasan#
- Nilai konfigurasi diberikan melalui
environment:yang langsung,${VAR}yang diinterpolasi dari berkas .env, atauenv_file:yang memuat berkas variabel utuh ke container. - Berkas .env melayani interpolasi Compose, sedangkan
env_file:melayani container, danenvironment:menimpa keduanya bila kuncinya bentrok. - compose.override.yaml dimuat otomatis dan menimpa nilai bawaan, sehingga pola bawaan produksi dengan override pengembangan bekerja tanpa opsi tambahan.
- Secret dideklarasikan dengan
file:pada kuncisecrets:tingkat atas dan diteruskan sebagai berkas di/run/secrets/, bukan sebagai variabel lingkungan.
Referensi#
- Environment variables — Docker Docs
— Panduan interpolasi berkas .env dan kunci
environment:beserta urutan prioritasnya. - Use secrets — Docker Docs
— Cara mendeklarasikan secret dengan
file:dan jalur pemasangannya di dalam container. - Working with multiple compose files — Docker Docs
— Aturan penggabungan compose.yaml dengan berkas override dan opsi
-f.