Penjelasan Variabel Lingkungan: .env File, Rahasia, dan Konfigurasi Dilakukan dengan Benar
Variabel lingkungan membiarkan kode yang sama dijalankan di laptop, di CI, dan produksi dengan pengaturan berbeda. Inilah perilaku mereka sebenarnya, dengan kejutan yang kami dapatkan saat mengujinya.
- Variabel lingkungan adalah pengaturan nilai kunci yang diterima suatu proses dari lingkungannya.
- Mereka menyimpan konfigurasi, seperti port dan URL database, dari kode Anda.
- Nilai selalu berupa string, jadi “false” adalah benar kecuali Anda menguraikannya.
- Jangan pernah melakukan
.envfile dengan rahasia nyata, dan validasi pengaturan yang diperlukan saat aplikasi dimulai.
Aplikasi Anda memerlukan URL database. Di laptop Anda, ini adalah database lokal, di CI adalah database sekali pakai, dan dalam produksi, cluster terkelola. Mengkodekan salah satu dari mereka berarti mengubah kode untuk setiap lingkungan. Variabel lingkungan menyelesaikan masalah ini. Kodenya berbunyi DATABASE_URL, dan setiap lingkungan memberikan nilainya sendiri.
Ide ini merupakan inti dari metode Aplikasi Dua Belas Faktor, yang menyatakan bahwa konfigurasi yang bervariasi antar penerapan di lingkungan. Kami menguji perilaku di bawah ini dengan Python 3.13 di Windows. Setiap keluaran yang ditampilkan berasal dari proses tersebut.
Apa yang dimaksud dengan variabel lingkungan?
Setiap proses yang berjalan memiliki sekumpulan nilai teks bernama yang disebut lingkungannya. Contoh yang lazim adalah PATH, yang memberi tahu shell di mana menemukan program, dan HOME atau USERPROFILE. Aplikasi Anda sendiri dapat menggunakan mekanisme yang sama untuk pengaturan seperti APP_PORT, LOG_LEVEL atau DATABASE_URL.
Mengatur variabel lingkungan
| cangkang | Untuk sesi ini | Untuk satu perintah |
|---|---|---|
| Pesta / zsh | ekspor APP_PORT=8080 |
APP_PORT=8080 aplikasi python.py |
| PowerShell | $env:APP_PORT = "8080" |
Atur, jalankan, lalu hapus |
| cmd jendela | setel APP_PORT=8080 |
Tidak terpasang |
Ini hanya berlangsung untuk sesi terminal saat ini. Untuk menjadikannya permanen, tambahkan ke profil shell seperti ~/.bashrc, atau, di Windows, gunakan pengaturan lingkungan sistem atau setx. Untuk aplikasi, biasanya lebih baik menyediakannya pada waktu penerapan daripada mengaturnya di seluruh sistem.
Membacanya dalam kode
import os
port = os.environ.get("APP_PORT", "8000") # default if missing
print(port) # 8000
db = os.environ["DATABASE_URL_MISSING_DEMO"]
# KeyError: 'DATABASE_URL_MISSING_DEMO'
Gunakan .get() dengan default untuk pengaturan opsional. Gunakan tanda kurung siku, yang memunculkan KeyError, untuk pengaturan yang tanpanya aplikasi tidak dapat berfungsi. Bahasa lain serupa: process.env.APP_PORT di Node.js, System.getenv("APP_PORT") di Java, dan os.Getenv("APP_PORT") di Go.
Semuanya adalah string
Ini menangkap orang-orang dalam setiap bahasa. Kami menetapkan port dan kemudian menambahkan “1” ke dalamnya:
os.environ["APP_PORT"] = "8080"
port = os.environ["APP_PORT"]
print(type(port).__name__, repr(port), port + "1")
# str '8080' 80801
os.environ["APP_PORT"] = 8080
# TypeError: str expected, not int
Nilainya kembali sebagai teks, dan penambahan menghasilkan 80801, bukan 8081. Konversi secara eksplisit, seperti pada int(os.environ["APP_PORT"]). Boolean lebih buruk:
os.environ["DEBUG"] = "false"
print(bool(os.environ["DEBUG"])) # True
String yang tidak kosong apa pun benar dalam Python, jadi "false" menjadi True. Mode debug akan diaktifkan dalam produksi. Parsing boolean dengan sengaja:
def env_bool(name, default=False):
value = os.environ.get(name)
if value is None:
return default
return value.strip().lower() in {"1", "true", "yes", "on"}
env_bool("DEBUG") # False
env_bool("NOT_SET", default=True) # True
Bagaimana proses mewarisinya
Proses anak menerima salinan dari lingkungan induknya. Kami memulai proses Python anak untuk melihat ini:
child sees: 8080 inherited # default: full copy of the parent's environment
child sees: 9000 None # given a custom env: only what we passed
parent sees child var: None # a child's changes never flow back
Tiga pelajaran praktis menyusul. Variabel yang Anda ekspor terlihat oleh setiap program yang Anda luncurkan, termasuk skrip yang tidak Anda tulis, yang penting bagi rahasia. Melewati lingkungan khusus menggantikan semuanya, jadi sertakan apa pun yang dibutuhkan anak. Dan skrip tidak dapat mengubah variabel shell induknya, itulah sebabnya alat meminta Anda source file alih-alih menjalankannya.
file .env
Mengetik banyak variabel dengan tangan akan membosankan, sehingga sebagian besar proyek menyimpan nilai pengembangan lokal dalam file .env:
# local development only
APP_PORT=8080
DATABASE_URL="postgres://dev:devonly@localhost:5432/shop"
FEATURE_SEARCH=true
Perpustakaan seperti python-dotenv, dan dotenv untuk Node.js, memuat file ini saat startup. Node.js 20.6 dan yang lebih baru juga dapat memuatnya secara asli dengan --env-file. Untuk melihat idenya, kami menulis parser kecil, yang mengubah file di atas menjadi:
{'APP_PORT': '8080',
'DATABASE_URL': 'postgres://dev:devonly@localhost:5432/shop',
'FEATURE_SEARCH': 'true'}
Gunakan perpustakaan nyata dalam praktiknya. Ini menangani kutipan, pelolosan, komentar, dan nilai multi-baris yang diabaikan oleh versi 10 baris kami. Secara default, sebagian besar pemuat dotenv tidak mengganti variabel yang telah disetel, sehingga nilai lingkungan nyata memenangkan file. Biasanya itulah yang Anda inginkan.
Kiat: Tambahkan .env ke .gitignore sebelum komit pertama Anda, dan komit .env.example dengan setiap nama variabel dan nilai placeholder aman. Pengembang baru menyalinnya dan mengisi nilainya sendiri.
Validasi konfigurasi saat startup
Variabel yang hilang harus segera menghentikan aplikasi dengan pesan yang jelas, tidak menyebabkan kesalahan yang membingungkan satu jam kemudian. Kami memeriksa pengaturan yang diperlukan saat memuat:
REQUIRED = ["DATABASE_URL", "SECRET_KEY"]
def check_required(env):
missing = [k for k in REQUIRED if not env.get(k)]
if missing:
raise SystemExit(f"Missing required settings: {', '.join(missing)}")
# Missing required settings: SECRET_KEY
Perpustakaan konfigurasi yang diketik melangkah lebih jauh. Pengaturan Pydantic dengan Python, zod atau envalid di Node.js, dan properti konfigurasi Spring di Java semuanya mengonversi tipe dan melaporkan setiap masalah sekaligus.
Variabel dan rahasia lingkungan
Variabel lingkungan adalah cara umum untuk meneruskan rahasia seperti kunci API ke aplikasi, dan variabel ini jauh lebih baik daripada melakukan hardcoding. Mereka memang memiliki kelemahan yang perlu diketahui:
- Proses anak mewarisinya, seperti yang ditunjukkan pengujian kami.
- Mereka dapat muncul di laporan kerusakan, halaman debug, dan log yang membuang lingkungan.
- Pada beberapa sistem, proses lain yang dijalankan oleh pengguna yang sama dapat membacanya.
Untuk produksi, banyak tim menyimpan rahasia di manajer khusus, seperti HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, atau Google Secret Manager, dan memasukkannya saat runtime. Beberapa lebih memilih memasang rahasia sebagai file daripada variabel. Apa pun yang terjadi, jangan pernah mencetak konfigurasi di log, dan merotasi rahasia apa pun yang pernah dikomit ke Git, bahkan setelah Anda menghapusnya dari riwayat.
Di Docker dan CI
# Docker (not run for this article)
docker run -e APP_PORT=8080 --env-file .env.production myapp
# GitHub Actions (not run for this article)
env:
APP_PORT: 8080
API_KEY: ${{ secrets.API_KEY }}
Platform CI menyimpan rahasia yang dienkripsi dan menyembunyikannya dalam log. Hindari memasukkan rahasia ke dalam image Docker dengan ENV di Dockerfile, karena rahasia tersebut tetap dapat dibaca di lapisan image. Lihat tutorial Docker Compose kami dan panduan CI/CD Tindakan GitHub untuk pengaturan lengkap.
Praktik terbaik
- Gunakan nama yang jelas dan huruf besar dengan awalan, misalnya
SHOP_DB_URL. - Baca semua konfigurasi dalam satu modul, konversi tipe di sana, dan validasi saat startup.
- Berikan default yang aman hanya untuk pengaturan yang tidak sensitif.
- Jauhkan
.envdari Git dan pertahankan.env.example. - Gunakan manajer rahasia dalam produksi untuk nilai-nilai sensitif.
- Dokumentasikan setiap variabel, tipenya, dan contoh nilai.
Men-debug masalah variabel lingkungan
Saat aplikasi berperilaku seolah-olah ada pengaturan yang hilang, lakukan pemeriksaan berikut secara berurutan:
- Apakah sudah diatur di tempat yang tepat? Variabel yang diekspor di satu tab terminal tidak ada di tab terminal lain, atau di layanan yang dimulai oleh sistem.
- Apakah aplikasi dimulai ulang? Proses yang berjalan mempertahankan lingkungan tempat aplikasi dimulai. Mengubah variabel setelahnya tidak berpengaruh hingga restart.
- Apakah namanya tepat? Nama peka huruf besar-kecil di Linux dan macOS, jadi
App_PortdanAPP_PORTmerupakan variabel yang berbeda. Windows memperlakukannya sama. - Apakah file .env menimpanya, atau diabaikan? Periksa apakah loader Anda mengabaikan nilai yang ada, dan file mana yang benar-benar dibaca.
- Apakah ada tanda kutip atau spasi yang menyimpang? Nilai yang disalin dengan spasi tambahan atau tanda kutip tambahan bisa gagal diurai, atau gagal dicocokkan, sehingga sulit dikenali.
Untuk melihat proses yang benar-benar diterima, cetak nama variabel, bukan nilai rahasianya. Di Linux dan macOS, printenv mencantumkan lingkungan shell saat ini, dan di PowerShell Get-ChildItem Env: melakukan hal yang sama. Di dalam container, menjalankan env hingga docker exec menampilkan tampilan container, yang sering kali berbeda dari tampilan shell Anda.
Tip terakhir: catat satu baris saat startup yang mencantumkan pengaturan opsional mana yang menggunakan defaultnya. Tidak ada biaya apa pun, dan sebagian besar menjawab “mengapa melakukan hal itu?” pertanyaan langsung.
Penutup
Variabel lingkungan itu sederhana, tetapi menyembunyikan beberapa jebakan: semuanya adalah string, turunan mewarisinya, dan rahasia dapat bocor melaluinya. Perlakukan mereka sebagai masukan untuk aplikasi Anda. Bacalah di satu tempat, konversikan dan validasi lebih awal, dan simpan rahasia nyata dari file yang dikomit.
Pertanyaan yang sering diajukan
Apa yang dimaksud dengan variabel lingkungan?
Ini adalah nilai teks bernama yang diterima suatu proses dari lingkungannya, seperti APP_PORT=8080. Aplikasi menggunakannya untuk pengaturan yang berubah antar lingkungan.
Apa itu file .env?
File teks baris KEY=value, dimuat saat startup oleh perpustakaan seperti python-dotenv. Ini digunakan terutama untuk pembangunan lokal dan tidak boleh dilakukan dengan rahasia nyata.
Mengapa variabel lingkungan saya berupa string?
Sistem operasi menyimpan nilai lingkungan sebagai teks. Konversikan angka dengan int() dan parsing boolean secara eksplisit, karena string “false” dihitung sebagai benar.
Apakah variabel lingkungan aman untuk rahasia?
Mereka lebih baik daripada hard-coding, namun proses anak mewarisinya dan log dapat mengeksposnya. Sistem produksi sering kali menggunakan manajer rahasia khusus.
Bisakah skrip mengubah variabel shell induknya?
Tidak. Proses anak mendapat salinan lingkungan, sehingga perubahannya tidak mengalir kembali. Untuk mengatur variabel di shell saat ini, sumberkan filenya.
Teruslah belajar
Butuh bantuan dengan pengujian, WordPress atau SEO?
Kami membantu tim mengirimkan perangkat lunak yang lebih baik dan mengembangkan situs mereka. Beritahu kami apa yang sedang Anda kerjakan dan kami akan menyarankan langkah selanjutnya yang jelas.
Panduan lebih lanjut tentang pengujian, AI & pengembangan modern
Menikmati artikel ini? Pilih topik dan langsung masuk ke tutorial terbaru kami.
Penjelasan Halusinasi AI: Mengapa Model Bahasa Memperbaiki Masalah dan Cara Menguranginya
Halusinasi AI menjelaskan: apa itu, mengapa model bahasa memproduksinya, tipe umum, cara menguranginya dengan landasan dan petunjuk, dan pemeriksaan…
Baca artikel →DevOpsPenjelasan Variabel Lingkungan: File .env, Rahasia, dan Konfigurasi Dilakukan dengan Benar
Variabel lingkungan dijelaskan dengan contoh Python yang kami jalankan: membaca dan mengaturnya, mengapa setiap nilai berupa string, file .env, pewa…
Baca artikel →Pengembangan perangkat lunakPenjelasan Pembatasan Kecepatan API: Algoritma, Header, dan Penanganan 429 Kesalahan
Pembatasan laju API dijelaskan dengan simulasi yang kami jalankan: keranjang token, jendela tetap, jendela geser, respons 429, header batas laju, pe…
Baca artikel →Otomatisasi pengujianMengejek dengan Python: unittest.mock, patch dan Kesalahan yang Membuat Tes Berbohong
Mengejek dengan Python dengan unittest.mock, menguji: Mock dan return_value, side_effect, menambal di mana nama digunakan, spesifikasi dan autospec,…
Baca artikel →Pengujian perangkat lunakPenjelasan Cakupan Kode: Cakupan Jalur vs Cabang dan Apa Arti 100% Sebenarnya
Cakupan kode dijelaskan dengan coverage.py yang sebenarnya dijalankan: cakupan garis, cabang dan kondisi, membaca laporan, mengapa cakupan 100% masi…
Baca artikel →Basis data & SQLDELETE vs TRUNCATE vs DROP dalam SQL: Perbedaan, Rollback dan Kapan Menggunakan Masing-Masing
DELETE vs TRUNCATE vs DROP dijelaskan dengan SQL yang diuji: apa yang dihapus, rollback, pemicu, reset identitas, kecepatan, dan perbedaan PostgreSQ…
Baca artikel →Basis data & SQLPenjelasan Tampilan SQL: Membuat, Menggunakan, dan Menghindari Kesalahan, Dengan Contoh
Tampilan SQL dijelaskan dengan kueri yang kami jalankan: membuat tampilan, hasil langsung, menyembunyikan kolom, kinerja, tampilan yang dapat diperb…
Baca artikel →Pengembangan perangkat lunakAntarmuka TypeScript vs Tipe: Perbedaan Nyata, Diuji Dengan Kompiler
Antarmuka TypeScript vs tipe, diperiksa dengan kompiler sebenarnya: apa yang bisa dilakukan keduanya, apa yang hanya bisa dilakukan satu orang, peng…
Baca artikel →Pengembangan perangkat lunakPenjelasan Python *args dan **kwargs: Fungsi Fleksibel Dengan Contoh Jelas
Python *args dan **kwargs dijelaskan dengan kode yang kami jalankan: pengepakan dan pembongkaran, urutan parameter, argumen hanya kata kunci dan pos…
Baca artikel →Pengembangan perangkat lunakFungsi Python Lambda: Sintaks, Kegunaan Sebenarnya, dan Kapan Tidak Digunakan
Fungsi python lambda dijelaskan dengan kode yang kami jalankan: sintaksis, pengurutan dengan kunci, peta dan filter, penutupan, jebakan pengikatan a…
Baca artikel →Kecerdasan buatanApa Itu Agen AI? Cara Kerjanya, Dengan Agent Loop Sederhana yang Dapat Anda Jalankan
Apa itu agen AI? Panduan sederhana tentang loop agen, alat, memori, dan pagar pembatas, dengan loop Python kecil yang kami jalankan, risiko nyata da…
Baca artikel →DevOpsPemantauan vs Observabilitas: Perbedaan Nyata, Dengan Log, Metrik, dan Jejak
Penjelasan pemantauan vs observabilitas: kegagalan yang diketahui dan tidak diketahui, log, metrik dan jejak, penelusuran insiden checkout, sinyal e…
Baca artikel →DevOpsVolume Docker vs Bind Mounts: Pertahankan Data Kontainer dengan Cara yang Benar
Volume Docker vs pengikatan pengikat dijelaskan: mengapa data kontainer menghilang, volume yang diberi nama, pengikatan pengikatan, tmpfs, contoh Tu…
Baca artikel →Otomatisasi pengujianTDD vs BDD: Perbedaan Utama, Satu Fitur Dibangun dengan Dua Cara dan Kapan Menggunakan Masing-masing
TDD vs BDD dijelaskan dengan satu fitur diskon yang dibuat dengan dua cara: refactor merah-hijau dengan kode yang kami jalankan, skenario Mengingat-…
Baca artikel →Pengembangan perangkat lunakGit merge vs rebase: perbedaan, contoh, dan kapan memakai masing-masing
Git merge vs rebase dijelaskan dengan keluaran log nyata, tabel perbandingan, aturan emas rebase, dan alur kerja tim yang aman.
Baca artikel →Pengembangan perangkat lunakList Comprehension Python: Sintaks, Contoh, dan Kapan Harus Dihindari
List comprehension Python dijelaskan: sintaks, filter, if-else, perulangan bersarang, waktu yang diukur, dan kapan perulangan for biasa lebih baik.
Baca artikel →Basis data & SQLPenjelasan SQL JOIN dengan Contoh (Inner, Left, Right, Full)
Pahami SQL JOIN langkah demi langkah dengan tabel dan query contoh: INNER, LEFT, RIGHT, FULL, CROSS, dan SELF, plus kesalahan umum dan tips performa.
Baca artikel →