Penjelasan Variabel Lingkungan: File .env, Rahasia, dan Konfigurasi Dilakukan dengan Benar

  1. Beranda
  2. Blog
  3. DevOps

DevOps

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.

8 menit baca
Penjelasan variabel lingkungan: file .env, rahasia, dan konfigurasi dilakukan dengan benar

Poin penting

  • 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 .env file 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 .env dari 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:

  1. 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.
  2. Apakah aplikasi dimulai ulang? Proses yang berjalan mempertahankan lingkungan tempat aplikasi dimulai. Mengubah variabel setelahnya tidak berpengaruh hingga restart.
  3. Apakah namanya tepat? Nama peka huruf besar-kecil di Linux dan macOS, jadi App_Port dan APP_PORT merupakan variabel yang berbeda. Windows memperlakukannya sama.
  4. Apakah file .env menimpanya, atau diabaikan? Periksa apakah loader Anda mengabaikan nilai yang ada, dan file mana yang benar-benar dibaca.
  5. 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

Bekerja dengan Stack Quora

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.

Teruslah membaca

Panduan lebih lanjut tentang pengujian, AI & pengembangan modern

Menikmati artikel ini? Pilih topik dan langsung masuk ke tutorial terbaru kami.

Kecerdasan buatan

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 →
DevOps

Penjelasan 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 lunak

Penjelasan 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 pengujian

Mengejek 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 lunak

Penjelasan 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 & SQL

DELETE 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 & SQL

Penjelasan 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 lunak

Antarmuka 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 lunak

Penjelasan 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 lunak

Fungsi 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 buatan

Apa 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 →
DevOps

Pemantauan 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 →
DevOps

Volume 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 pengujian

TDD 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 lunak

Git 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 lunak

List 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 & SQL

Penjelasan 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 →