SSD Nodes Learn 8GB RAM — yılda $66
Rehberler Matt ConnorYazan Matt Connor · Güncellendi 2026-08-01

Docker Compose .env, env_file ve secrets farkları

Docker Compose'ta .env, env_file ve environment farklarını, öncelik sırasını ve parolaların neden environment yerine secrets ile saklanması gerektiğini öğrenin.

İnsanların env dosyası olarak adlandırdığı üç şey

Docker Compose, adları birbirine benzediği için karıştırılabilen üç ayrı mekanizma sunar. .env dosyası, Compose dosyayı ayrıştırmadan önce compose.yaml içindeki ${VARIABLE} yer tutucularını doldurur. env_file: özniteliği, anahtar/değer çiftlerinden oluşan bir dosyayı container ortamına yükler. environment: özniteliği ise değişkenleri compose dosyasında doğrudan tanımlayarak container üzerinde ayarlar. Bunlar birbirinin yerine kullanılamaz. İkisi aynı anahtarı ayarladığında, hangi değerin geçerli olacağı belgelenmiş bir öncelik sırasına göre belirlenir.

Bu kılavuzda her mekanizmanın nasıl çalıştığı gösterilir. Ardından çalıştırılabilecek bir komutla öncelik sırası doğrulanır. Daha önemli konu da ele alınır: ortam değişkenleri docker inspect çalıştırabilen herkes tarafından okunabilir. Bu nedenle parolalar ortam değişkenlerinde tutulmamalıdır. Compose dosyalarını genel olarak kullanmaya yeni başlanıyorsa, VPS üzerinde Docker Compose temelleri ile başlanabilir ve yapılandırma için buraya dönülebilir.

.env dosyası container için değil, compose dosyası içindir

Bir dizin oluşturun ve içine iki dosya yerleştirin.

mkdir -p ~/envdemo && cd ~/envdemo
printf 'ALPINE_TAG=3.20\n' > .env
services:
  demo:
    image: alpine:${ALPINE_TAG}
    command: printenv ALPINE_TAG

Şimdi Compose'un gerçekte neyi ayrıştırdığını kontrol edin.

docker compose config

Çıktıda image: alpine:3.20 gösterilir. Yer tutucu artık yoktur, çünkü enterpolasyon ayrıştırma sırasında gerçekleşmiştir. Compose, proje dizininde, yani compose dosyasının bulunduğu dizinde .env dosyasını arar ve bulduğu her ${NAME} ifadesini değiştirir.

Ardından servisi çalıştırın.

docker compose run --rm demo

printenv ALPINE_TAG 1 durum koduyla çıkar ve hiçbir çıktı vermez. Değişken container içinde mevcut değildir. En yaygın yanlış anlama budur: .env compose dosyasını yapılandırır, işlemi değil. İçinde POSTGRES_PASSWORD=hunter2 bulunan bir .env dosyası, compose dosyasının herhangi bir bölümü bu dosyaya başvurmuyorsa veritabanınız için hiçbir işlem yapmaz.

${NAME:-default}, değişken ayarlanmamışsa veya boşsa bir varsayılan değer sağlar. ${NAME:?message} ise Compose'un başlatmayı reddetmesini ve belirttiğiniz mesajı yazdırmasını sağlar. Güvenli bir varsayılan değeri olmayan bir değer için doğru seçim budur.

env_file değişkenleri container içine yükler

env_file: özniteliği, içerikleri container ortam değişkenlerine dönüştürülen bir veya daha fazla dosyanın adını belirtir.

printf 'GREETING=from_env_file\nAPP_MODE=production\n' > app.env
services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    env_file:
      - ./app.env
docker compose run --rm demo

Bu komut from_env_file çıktısını verir. Dosya biçimi, her satırda bir tane bulunan düz KEY=value satırlarından oluşur. Yorumlar # ile başlatılır. Bu biçim shell biçimi değildir. Çoğu durumda tırnak işaretleri değerin parçası olarak korunur ve export önekleri gerekli değildir. = işaretinin çevresine boşluk koyulmamalıdır. Aksi halde KEY = value değeri, değerinin başında boşluk bulunan ve adı kelimesi kelimesine KEY olan bir değişken oluşturur.

Bulunmayan env_file yolu hatadır ve Compose çalışmayı durdurur. Dosya geçerli olarak bulunmayabilecekse dosyayı isteğe bağlı olarak işaretleyin:

    env_file:
      - path: ./app.env
        required: false

environment değişkenleri satır içinde ayarlar

services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    environment:
      GREETING: from_environment

Yukarıdaki eşleme biçimi ve - GREETING=from_environment kullanan liste biçimi olmak üzere 2 söz dizimi kabul edilir. İkisi de aynı şekilde çalışır. Liste biçiminin bir ek özelliği vardır: Değeri olmayan yalın bir anahtar, değişkeni docker compose komutunu çalıştırdığınız kabuktan aktarır.

    environment:
      - GREETING
GREETING=from_my_shell docker compose run --rm demo

Bu işlem from_my_shell çıktısını verir. Kabukta GREETING ayarlanmadan çalıştırıldığında Compose hiçbir değer ayarlamaz ve uyarı vermez. Sessiz geçiş hatlarının bilinmesi önemlidir. Boş bir parola değişkeniyle başlatılan bir hizmet çoğu zaman başarıyla başlar, ancak tamamen korumasız kalır.

Hangisi öncelikli

Docker, öncelik sırasını en yüksekten başlayarak belgeler: önce komut satırındaki docker compose run -e, ardından değeri kabuğunuzdan veya bir env dosyasından enterpole edilen environment ya da env_file, sonra compose dosyasındaki düz environment, ardından env_file ve son olarak image içine yerleştirilmiş ENV yönergesi.

Günlük kullanım için kısa özet: environment:, env_file: değerine üstün gelir; komut satırındaki -e ise her ikisine de üstün gelir. Bunu tek bir dosyada doğrulayın.

services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    env_file:
      - ./app.env
    environment:
      GREETING: from_environment
docker compose run --rm demo
docker compose run --rm -e GREETING=from_cli demo printenv GREETING

İlk komut from_environment çıktısını verir. Bunun nedeni environment: değerinin app.env içindeki değerin üzerine yazmasıdır. İkinci komut from_cli çıktısını verir. Compose dosyasındaki hiçbir ayar komut satırındaki değerin üzerine yazmaz.

Bir container, yapılandırmanız hiç uygulanmamış gibi davranıyorsa tahminde bulunmayın. docker compose config, tamamen çözümlenmiş dosyayı yazdırır. docker compose config --environment ise Compose'un kullandığı enterpolasyon değişkenlerini yazdırır. "env dosyam yok sayılıyor" bildirimlerinin çoğunda aynı değer iki farklı düzeyde tanımlanmıştır.

Ortam değişkenleri neden sızar

environment: içine bir parola ayarlanırsa parola, diskteki container yapılandırmasında depolanır ve docker grubundaki tüm kullanıcılar tarafından görülebilir.

docker compose run -d --name leaky -e DB_PASSWORD=hunter2 demo sleep 300
docker inspect leaky --format '{{json .Config.Env}}'

Çıktı, "DB_PASSWORD=hunter2" değerini düz metin olarak içerir. Üç ek yol da aynı değeri açığa çıkarır. docker compose config bu değeri terminale yazdırır. Değer bu şekilde bir destek forumuna yapıştırılır. Container içindeki herhangi bir işlem /proc/1/environ değerini okuyabilir ve her alt işlem bu değişkeni devralır. Ayrıca uygulamaların çökme işleyicileri, ortamın tamamını rutin olarak bir günlüğe veya hata raporuna döker.

docker grubuna üyelik, host üzerinde fiilen root yetkisine eşdeğerdir. Bu nedenle bu üyelik, güvenilebilecek bir ayrıcalık sınırı değildir. VPS üzerinde en az ayrıcalıklı kullanıcı hesapları kılavuzu, paylaşımlı herhangi bir sunucuda bu grubun neden kısıtlanması gerektiğini açıklar.

Compose secret değerini bir dosyada tutar

Compose, dosya tabanlı secret'ları destekler. Değer, ortama aktarılmak yerine container içine dosya olarak mount edilir.

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
secrets:
  db_password:
    file: ./db_password.txt

Secret, container içinde /run/secrets/db_password yoluna mount edilir. Eğik çizgiden sonraki ad, üst düzey secrets: bloğundaki secret adıdır.

_FILE son eki, postgres, mysql ve mariadb dahil Docker Official Images tarafından kullanılan bir kuraldır. Bu entrypoint script'leri VARNAME_FILE değerini kontrol eder, dosyayı okur ve içeriğini kullanır. Bu bir Docker özelliği değildir. Bu nedenle yalnızca image bunu uyguluyorsa çalışır. SOMETHING_FILE değerinin dikkate alınacağını varsaymadan önce image belgelerini kontrol edin. Bunu desteklemeyen uygulamalar, başlangıçta dosyayı kendileri okuyabilir. Alternatif olarak yolu aktarabilir ve işlemi kendi entrypoint'inize yaptırabilirsiniz.

Çalışan container içinden doğrulayın:

docker compose exec db cat /run/secrets/db_password
docker compose exec db printenv POSTGRES_PASSWORD

İlk komut parolayı yazdırır. İkinci komut hiçbir şey yazdırmaz, çünkü değer ortama hiç aktarılmamıştır. Amaç tam olarak budur: Bu container üzerindeki docker inspect yalnızca zararsız yolu gösterir.

Secret, arkasındaki dosya kadar gizli olduğundan host üzerindeki kaynak dosyayı koruyun:

chmod 600 db_password.txt

VPS üzerinde uygulanabilir orta yol

Birçok self-hosted imaj _FILE değişkenlerini desteklemez. Bu nedenle içeriye geçiş için tek yol ortam değişkenleridir. Tek yöneticili bir VPS'te gerçekçi hedef, değerlerin proje dizininde herkes tarafından okunabilen bir dosyada bulunmasını önlemek ve bunları git dışında tutmaktır.

sudo install -o root -g root -m 600 /dev/null /etc/myapp/app.env
sudo nano /etc/myapp/app.env
    env_file:
      - /etc/myapp/app.env

install -m 600 dosyayı, izinleri baştan ayarlanmış şekilde oluşturur. Böylece dosyanın herkes tarafından okunabildiği bir zaman aralığı oluşmaz. Dosyanın sahibi root hesabıdır. Bu nedenle makinedeki root olmayan bir kullanıcı dosyayı okuyamaz. Ancak docker çalıştırabilen herkes değeri yine de container içinden okuyabilir. *.env ve .env satırlarını .gitignore dosyasına ekleyin. Bunun yerine anahtar adlarını boş değerlerle içeren bir app.env.example dosyasını commit edin. Commit edilmiş bir parola değiştirilmiş parola kabul edilir.

Bir değeri değiştirmek servisin yeniden başlatılmasını gerektirir. Ortam değişkenleri container işlemi başlatıldığında bir kez okunur. Bu nedenle dosyayı düzenlemek, docker compose up -d --force-recreate db çalıştırılana kadar hiçbir şeyi değiştirmez. Bu, VPS üzerinde HTTPS arkasında n8n kılavuzunda kullanılan yöntemin aynısıdır. Bu yöntemde şifreleme anahtarı compose dosyasının dışında tutulur.

Ortama göre yapılandırmayı ayırma

Compose, varsayılan olarak .env dosyasını proje dizininden okur. --env-file ile başka bir konum belirtilebilir.

docker compose --env-file .env.staging config

Birden çok dosya sırayla okunur ve sonraki dosyalardaki değerler önceki değerleri geçersiz kılar. Gizli olmayan varsayılan değerler sürüm denetimine alınan bir dosyada, gizli bilgiler ise sunucudan hiçbir zaman çıkarılmayan bir dosyada tutulmalıdır. Aynı durum env_file: için de geçerlidir; yinelenen bir anahtar için listelenen son dosyanın değeri geçerli olur.

FAQ

.env dosyam neden container içinde yok sayılıyor?

Yok sayılmıyor. .env dosyası yalnızca compose dosyasındaki ${NAME} yer tutucularını değiştirir. Container içindeki değişkenleri hiçbir zaman ayarlamaz. Değeri container içine aktarmak için environment: { KEY: "${NAME}" } öğesine başvurun veya bunun yerine env_file: ./that-file.env kullanın.

environment, env_file değerini geçersiz kılar mı, yoksa tersi mi geçerlidir?

environment: önceliklidir. Docker'ın belgelenmiş öncelik sıralamasında environment özniteliği env_file özniteliğinin üzerinde, her ikisi de komut satırındaki docker compose run -e değerinin altında yer alır. Bir anahtar her iki yerde de ayarlanırsa env_file içindeki değer sessizce kullanılmaz.

Compose'un kullanacağı nihai değeri nasıl görebilirim?

Tüm enterpolasyon uygulanmış, tamamen çözümlenmiş compose dosyasını yazdırmak için docker compose config komutunu çalıştırın. Zaten çalışmakta olan bir container için docker inspect <container> --format '{{json .Config.Env}}', işlemin aldığı değerleri tam olarak gösterir.

Compose secret değerleri şifrelenir mi?

Hayır. Dosya tabanlı bir secret, /run/secrets/<name> konumunda düz metin dosyası olarak container içine bağlanır ve kaynak dosya host diskinde şifrelenmeden tutulur. Avantaj şifreleme değil, kapsamın sınırlı olmasıdır: değer container ortamından, docker inspect çıktısından ve ortam değişkenlerini yazdıran crash dump'larından uzak kalır.

Bir env dosyasında tırnak ve boşluk kullanabilir miyim?

KEY=value with spaces kullanın ve tırnakları eklemeyin. Compose, satırın geri kalanının tamamını değer olarak kabul eder. Bu nedenle tırnaklar genellikle değerde gerçek karakterler olarak kalır. = çevresine hiçbir zaman boşluk koymayın. Aksi halde anahtarın sonunda boşluk bulunur ve hiçbir değer bununla eşleşmez.