Açıklanan Ortam Değişkenleri: .env Dosyaları, Sırlar ve Yapılandırma Doğru Yapıldı

  1. Ana sayfa
  2. Blog
  3. DevOps

DevOps

Açıklanan Ortam Değişkenleri: .env Dosyaları, Sırlar ve Yapılandırma Doğru Yapıldı

Ortam değişkenleri aynı kodun bir dizüstü bilgisayarda, CI’da ve üretimde farklı ayarlarla çalıştırılmasına izin verir. İşte onları test ederken karşılaştığımız sürprizlerle gerçekte nasıl davrandıkları.

8 dk okuma
Ortam değişkenlerinin açıklaması: .env dosyaları, sırlar ve yapılandırma doğru şekilde yapıldı

Önemli noktalar

  • Ortam değişkenleri, bir işlemin ortamından aldığı anahtar/değer ayarlarıdır.
  • Bağlantı noktaları ve veritabanı URL’leri gibi yapılandırmaları kodunuzun dışında tutarlar.
  • Değerler her zaman dizelerdir, dolayısıyla siz onu ayrıştırmadığınız sürece “yanlış” doğrudur.
  • Hiçbir zaman gerçek sırlara sahip .env dosyaları işlemeyin ve uygulama başlatıldığında gerekli ayarları doğrulayın.

Uygulamanızın bir veritabanı URL’sine ihtiyacı var. Dizüstü bilgisayarınızda yerel bir veritabanıdır, CI’da tek kullanımlıktır ve üretimde yönetilen bir kümedir. Bunlardan herhangi birinin sabit kodlanması, her ortam için kodun değiştirilmesi anlamına gelir. Ortam değişkenleri bunu çözer. Kod DATABASE_URL‘yi okur ve her ortam kendi değerini sağlar.

Bu fikir, dağıtımlar arasında değişen yapılandırmaların ortama ait olduğunu söyleyen On İki Faktörlü Uygulama yönteminin merkezinde yer alır. Aşağıdaki davranışı Windows’ta Python 3.13 ile test ettik. Gösterilen her çıktı bu çalıştırmadan alınmıştır.

Ortam değişkenleri nelerdir?

Çalışan her işlemin, ortamı adı verilen bir dizi adlandırılmış metin değeri vardır. Bilinen örnekler, kabuğa programları nerede bulacağını söyleyen PATH ve HOME veya USERPROFILE‘tür. Kendi uygulamanız APP_PORT, LOG_LEVEL veya DATABASE_URL gibi ayarlar için aynı mekanizmayı kullanabilir.

Ortam değişkenlerini ayarlama

Kabuk Bu oturum için Bir komut için
Bash / zsh APP_PORT=8080'i dışa aktar APP_PORT=8080 python app.py
PowerShell $env:APP_PORT = "8080" Ayarlayın, çalıştırın ve ardından kaldırın
Windows cmd’si APP_PORT=8080'i ayarla Yerleşik değil

Bunlar yalnızca geçerli terminal oturumu için geçerlidir. Bunları kalıcı kılmak için, bunları ~/.bashrc gibi bir kabuk profiline ekleyin veya Windows’ta sistem ortamı ayarlarını veya setx kullanın. Uygulamalar için, bunları sistem genelinde ayarlamak yerine dağıtım zamanında sağlamak genellikle daha iyidir.

Bunları kod halinde okumak

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'

İsteğe bağlı ayarlar için varsayılan değerle .get() kullanın. Uygulamanın onsuz çalışamayacağı ayarlar için KeyError değerini yükselten köşeli parantezleri kullanın. Diğer diller de benzerdir: Node.js’de process.env.APP_PORT, Java’da System.getenv("APP_PORT") ve Go’da os.Getenv("APP_PORT").

Her şey bir dizedir

Bu her dilden insanı yakalar. Bir bağlantı noktası belirledik ve ardından ona “1” ekledik:

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

Değer metin olarak geri geldi ve eklenmesi 8081 değil 80801 sonucunu verdi. int(os.environ["APP_PORT"])‘deki gibi açıkça dönüştürün. Boolean’lar daha kötü:

os.environ["DEBUG"] = "false"
print(bool(os.environ["DEBUG"]))   # True

Boş olmayan herhangi bir dize Python’da doğrudur, bu nedenle "false", True oldu. Hata ayıklama modu üretimde açılmış olurdu. Boolean’ları kasıtlı olarak ayrıştırın:

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

Süreçler onları nasıl miras alır?

Bir alt süreç, üst ortamının kopyasını alır. Bunu görmek için alt Python işlemlerini başlattık:

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

Bunu üç pratik ders takip ediyor. Dışa aktardığınız değişkenler, yazmadığınız komut dosyaları da dahil olmak üzere (gizler için önemli olan) başlattığınız her program tarafından görülebilir. Özel bir ortamın geçmesi her şeyin yerini alır, bu nedenle çocuğun ihtiyaç duyduğu her şeyi ekleyin. Ve bir komut dosyası ana kabuğunun değişkenlerini değiştiremez; bu nedenle araçlar sizden bir dosyayı çalıştırmak yerine source yapmanızı ister.

.env dosyaları

Birçok değişkeni elle yazmak sıkıcı olur, bu nedenle çoğu proje yerel geliştirme değerlerini bir .env dosyasında tutar:

# local development only
APP_PORT=8080
DATABASE_URL="postgres://dev:devonly@localhost:5432/shop"
FEATURE_SEARCH=true

Python-dotenv ve Node.js için dotenv gibi kitaplıklar bu dosyayı başlangıçta yükler. Node.js 20.6 ve üzeri, --env-file ile yerel olarak da yüklenebilir. Fikri anlamak için yukarıdaki dosyayı şuna dönüştüren küçük bir ayrıştırıcı yazdık:

{'APP_PORT': '8080',
 'DATABASE_URL': 'postgres://dev:devonly@localhost:5432/shop',
 'FEATURE_SEARCH': 'true'}

Pratikte gerçek bir kütüphane kullanın. 10 satırlık versiyonumuzun göz ardı ettiği alıntılama, kaçış, yorum ve çok satırlı değerleri yönetir. Varsayılan olarak çoğu dotenv yükleyici, önceden ayarlanmış değişkenleri geçersiz kılmazdeğildir, böylece gerçek ortam değerleri dosyanın üzerinde kazanır. Genellikle istediğin budur.

İpucu: İlk işleminizden önce .env‘yi .gitignore‘e ekleyin ve bunun yerine her değişken adı ve güvenli yer tutucu değerleri ile bir .env.example kaydedin. Yeni geliştiriciler bunu kopyalayıp kendi değerlerini doldururlar.

Başlangıçta yapılandırmayı doğrulayın

Eksik bir değişken, açık bir mesajla uygulamayı hemen durdurmalı, bir saat sonra kafa karıştırıcı bir hataya neden olmamalıdır. Yükleme sırasında gerekli ayarları kontrol ettik:

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

Yazılan yapılandırma kitaplıkları daha da ileri gider. Python’daki Pydantic Ayarları, Node.js’deki zod veya envalid ve Java’daki Spring’in yapılandırma özelliklerinin tümü türleri dönüştürür ve her sorunu aynı anda bildirir.

Ortam değişkenleri ve sırlar

Ortam değişkenleri, API anahtarları gibi sırları bir uygulamaya aktarmanın yaygın yoludur ve bunları sabit kodlamaktan çok daha iyidir. Bilmeleri gereken zayıf yönleri var:

  • Testimizin gösterdiği gibi çocuk süreçleri onları miras alır.
  • Ortamı boşaltan kilitlenme raporlarında, hata ayıklama sayfalarında ve günlüklerde görünebilirler.
  • Bazı sistemlerde aynı kullanıcı tarafından çalıştırılan diğer işlemler bunları okuyabilir.

Üretim için birçok ekip, sırları HashiCorp Vault, AWS Secrets Manager, Azure Key Vault veya Google Secret Manager gibi özel bir yöneticide saklar ve bunları çalışma zamanında enjekte eder. Bazıları sırları değişkenler yerine dosyalar olarak birleştirmeyi tercih ediyor. Her iki durumda da, asla günlüklerdeki yapılandırmaları yazdırmayın ve Git’e aktarılmış herhangi bir sırrı geçmişten kaldırdıktan sonra bile döndürün.

Docker ve CI’da

# 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 }}

CI platformları sırları şifrelenmiş olarak saklar ve bunları günlüklerde maskeler. Docker dosyasındaki ENV ile Docker görüntülerine sırlar eklemekten kaçının çünkü bunlar görüntü katmanlarında okunabilir durumda kalır. Kurulumların tamamı için Docker Compose eğitimimize ve GitHub Actions CI/CD kılavuzuna bakın.

En iyi uygulamalar

  • SHOP_DB_URL gibi bir önekle birlikte anlaşılır, büyük harfli adlar kullanın.
  • Tüm yapılandırmaları tek bir modülde okuyun, türleri orada dönüştürün ve başlangıçta doğrulayın.
  • Yalnızca hassas olmayan ayarlar için güvenli varsayılanlar sağlayın.
  • .env‘i Git’ten uzak tutun ve bir .env.example‘yi koruyun.
  • Hassas değerler için üretimde bir gizli dizi yöneticisi kullanın.
  • Her değişkeni, türünü ve örnek değerini belgeleyin.

Ortam değişkeni problemlerinde hata ayıklama

Bir uygulama, bir ayar eksikmiş gibi davrandığında şu kontrolleri sırayla gerçekleştirin:

  1. Doğru yere ayarlanmış mı? Bir terminal sekmesinde dışa aktarılan bir değişken, diğerinde veya sistem tarafından başlatılan bir hizmette mevcut değil.
  2. Uygulama yeniden başlatıldı mı? Çalışan bir işlem, başlatıldığı ortamı korur. Daha sonra bir değişkeni değiştirmenin yeniden başlatmaya kadar hiçbir etkisi yoktur.
  3. Ad tam mı? Linux ve macOS’ta adlar büyük/küçük harfe duyarlıdır, dolayısıyla App_Port ve APP_PORT farklı değişkenlerdir. Windows onlara aynı şekilde davranır.
  4. Bir .env dosyası onu geçersiz kılıyor mu, yoksa yok sayılıyor mu? Yükleyicinizin mevcut değerleri geçersiz kılıp kılmadığını ve gerçekte hangi dosyayı okuduğunu kontrol edin.
  5. Başıboş tırnak işaretleri veya boşluklar var mı? Sonunda boşluk veya fazladan tırnak işaretleri ile kopyalanan bir değer, fark edilmesi zor şekillerde ayrıştırılamayabilir veya eşleşmeyebilir.

Bir sürecin gerçekte ne aldığını görmek için değişken adlarını yazdırın, gizli dizilerin değerlerini asla yazdırmayın. Linux ve macOS’ta printenv mevcut kabuğun ortamını listeler ve PowerShell’de Get-ChildItem Env: de aynısını yapar. Bir konteynerin içinde, env‘ten docker exec‘e kadar çalışmak, konteynerin görünümünü gösterir ve bu genellikle kendi kabuğunuzunkinden farklıdır.

Son bir ipucu: başlangıçta hangi isteğe bağlı ayarların varsayılanlarını kullandığını listeleyen bir satır kaydedin. Hiçbir maliyeti yok ve çoğu kişinin cevabını “bunu neden yapıyor?” hemen sorular.

Son sözler

Ortam değişkenleri basittir ancak birkaç tuzağı gizlerler: Her şey bir iptir, çocuklar bunları miras alır ve sırlar bunlardan sızabilir. Bunları uygulamanıza bir girdi olarak değerlendirin. Bunları tek bir yerde okuyun, erkenden dönüştürüp doğrulayın ve gerçek sırları işlenen dosyalardan uzak tutun.

Sık sorulan sorular

Ortam değişkeni nedir?

Bir işlemin kendi ortamından aldığı, APP_PORT=8080 gibi adlandırılmış bir metin değeridir. Uygulamalar bunları ortamlar arasında değişen ayarlar için kullanır.

.env dosyası nedir?

Başlangıçta python-dotenv gibi bir kitaplık tarafından yüklenen KEY=value satırlarından oluşan bir metin dosyası. Esas olarak yerel kalkınma için kullanılır ve gerçek sırlarla işlenmemelidir.

Ortam değişkenim neden bir dize?

İşletim sistemleri ortam değerlerini metin olarak saklar. Sayıları int() ile dönüştürün ve “false” dizesi doğru olarak sayıldığından booleanları açıkça ayrıştırın.

Ortam değişkenleri sırlar açısından güvenli midir?

Sabit kodlamadan daha iyidirler ancak alt süreçler bunları devralır ve günlükler bunları açığa çıkarabilir. Üretim sistemleri genellikle özel bir sır yöneticisi kullanır.

Bir komut dosyası ana kabuğunun değişkenlerini değiştirebilir mi?

Hayır. Bir alt süreç ortamın bir kopyasını alır, dolayısıyla değişiklikleri geri akmaz. Geçerli kabuktaki değişkenleri ayarlamak için bunun yerine dosyayı kaynaklayın.

Öğrenmeye devam et

Stack Quora ile çalışın

Test, WordPress veya SEO konusunda yardıma mı ihtiyacınız var?

Ekiplerin daha iyi yazılımlar sunmasına ve sitelerini büyütmesine yardımcı oluyoruz. Bize ne üzerinde çalıştığınızı söyleyin, biz de bir sonraki adım için net bir öneride bulunalım.

Okumaya devam et

Daha fazla kılavuz test, yapay zeka ve modern geliştirme

Bu makaleyi beğendiniz mi? Bir konu seçin ve doğrudan en yeni eğitimlerimize geçin.

Yapay zekâ

Yapay Zeka Halüsinasyonları Açıklandı: Dil Modelleri Neden İşleri Düzeltiyor ve Nasıl Azaltılabilir?

Yapay zeka halüsinasyonları açıkladı: ne olduklarını, dil modellerinin bunları neden ürettiğini, yaygın türlerini, temellendirme ve yönlendirmelerle…

Makaleyi okuyun →
DevOps

Açıklanan Ortam Değişkenleri: .env Dosyaları, Sırlar ve Yapılandırma Doğru Yapıldı

Çalıştırdığımız Python örnekleriyle açıklanan ortam değişkenleri: bunları okumak ve ayarlamak, neden her değerin bir dize olduğu, .env dosyaları, sü…

Makaleyi okuyun →
Yazılım geliştirme

API Hız Sınırlamasının Açıklaması: Algoritmalar, Başlıklar ve 429 Hatalarının Ele Alınması

API hızı sınırlaması, çalıştırdığımız bir simülasyonla açıklanmıştır: belirteç kümesi, sabit pencere, kayan pencere, 429 yanıt, hız sınırı başlıklar…

Makaleyi okuyun →
Test otomasyonu

Python'da alay etme: Unittest.mock, patch ve Testleri Yalan Yapan Hatalar

Unittest.mock ile Python'da alay etme, test edildi: Sahte ve dönüş_değeri, yan_etki, bir adın kullanıldığı yerde yama uygulama, spesifikasyon ve oto…

Makaleyi okuyun →
Yazılım testi

Kod Kapsamının Açıklaması: Hat ve Şube Kapsamı ve %100'ün Gerçek Anlamı

Kod kapsamı gerçek bir kapsama.py çalışmasıyla açıklanmıştır: hat, şube ve durum kapsamı, bir raporun okunması, %100 kapsamın neden hâlâ hataları ka…

Makaleyi okuyun →
Veritabanları ve SQL

SQL'de DELETE vs TRUNCATE vs DROP: Farklılıklar, Geri Alma ve Her Biri Ne Zaman Kullanılmalı

DELETE vs TRUNCATE vs DROP test edilmiş SQL ile açıklandı: her birinin neyi kaldırdığı, geri aldığı, tetiklediği, kimlik sıfırlaması, hızı ve Postgr…

Makaleyi okuyun →
Veritabanları ve SQL

Açıklanan SQL Görünümleri: Örneklerle Tuzakları Oluşturun, Kullanın ve Önleyin

Çalıştırdığımız sorgularla açıklanan SQL görünümleri: görünüm oluşturma, canlı sonuçlar, sütunları gizleme, performans, güncellenebilir ve gerçekleş…

Makaleyi okuyun →
Yazılım geliştirme

TypeScript Arayüzü ve Tür: Gerçek Farklılıklar, Derleyiciyle Test Edildi

TypeScript arayüzü ve türü, gerçek derleyiciyle kontrol edildi: her ikisinin de yapabileceği, yalnızca birinin yapabileceği, bildirim birleştirme, g…

Makaleyi okuyun →
Yazılım geliştirme

Python *args ve **kwargs'ın Açıklaması: Açık Örneklerle Esnek Fonksiyonlar

Python *args ve **kwargs çalıştırdığımız kodla açıklanmıştır: paketleme ve paketten çıkarma, parametre sırası, yalnızca anahtar kelime ve yalnızca k…

Makaleyi okuyun →
Yazılım geliştirme

Python Lambda İşlevleri: Söz Dizimi, Gerçek Kullanımlar ve Ne Zaman Kullanılmaması Gerektiği

Çalıştırdığımız kodla açıklanan Python lambda işlevleri: sözdizimi, anahtarla sıralama, harita ve filtre, kapatmalar, geç bağlama tuzağı ve normal b…

Makaleyi okuyun →
Yapay zekâ

Yapay Zeka Ajanları Nelerdir? Çalıştırabileceğiniz Basit Bir Aracı Döngüsüyle Nasıl Çalışırlar?

Yapay zeka ajanları nedir? Aracı döngüsüne, araçlara, belleğe ve korkuluklara ilişkin basit bir kılavuz, çalıştırdığımız küçük bir Python döngüsü, g…

Makaleyi okuyun →
DevOps

İzleme ve Gözlemlenebilirlik: Günlükler, Metrikler ve İzlerle Gerçek Fark

İzleme ve gözlemlenebilirliğin açıklanması: bilinen ve bilinmeyen arızalar, günlükler, ölçümler ve izler, ödeme olayının gözden geçirilmesi, altın s…

Makaleyi okuyun →
DevOps

Docker Birimleri ve Bağlama Bağlantıları: Konteyner Verilerini Doğru Şekilde Kalıcılaştırın

Docker birimleri ile bağlama bağlamaları arasındaki karşılaştırma açıklandı: kapsayıcı verilerinin neden kaybolduğu, adlandırılmış birimler, bağlama…

Makaleyi okuyun →
Test otomasyonu

TDD ve BDD: Temel Farklılıklar, Her İki Şekilde Geliştirilmiş Bir Özellik ve Her Birinin Ne Zaman Kullanılacağı

TDD ve BDD, her iki yönde de oluşturulmuş bir indirim özelliğiyle açıklandı: çalıştırdığımız kodla kırmızı-yeşil-refactor, Verilen-Ne Zaman-O Zaman …

Makaleyi okuyun →
Yazılım geliştirme

Git merge vs rebase: farklar, örnekler ve hangisi ne zaman kullanılır

Git merge vs rebase; gerçek log çıktısı, karşılaştırma tablosu, rebase'in altın kuralı ve güvenli bir ekip iş akışıyla anlatılıyor.

Makaleyi okuyun →
Yazılım geliştirme

Python Liste Üreteci (List Comprehension): Sözdizimi, Örnekler ve Kaçınılacak Durumlar

Python list comprehension anlatımı: sözdizimi, filtreleme, if-else, iç içe döngüler, ölçülmüş süreler ve düz for döngüsünün daha iyi olduğu durumlar.

Makaleyi okuyun →
Veritabanları ve SQL

SQL JOIN Örneklerle Açıklama (Inner, Left, Right, Full)

SQL JOIN'leri örnek tablolar ve sorgularla adım adım öğrenin: INNER, LEFT, RIGHT, FULL, CROSS ve SELF; yaygın hatalar ve performans ipuçları.

Makaleyi okuyun →