Docker Compose'ta değişken interpolasyonu, Compose dosyasındaki ${TAG} veya $TAG gibi ifadelerin, uygulama modeli oluşturulmadan önce kabuk ortamından, proje dizinindeki .env dosyasından ya da --env-file ile verdiğiniz dosyadan gelen değerlerle değiştirilmesidir. ${VAR:-varsayılan} ile varsayılan değer, ${VAR:?ileti} ile zorunlu değer tanımlayabilirsiniz. Sonucu her zaman docker compose config ile görebilirsiniz; bu yazıdaki tüm çıktılar bu komutla Docker Compose v5.5.1 üzerinde alındı.
Interpolasyon, container'ın içindeki ortam değişkenleriyle aynı şey değildir. Interpolasyon Compose dosyasının metnini çözer; container ortamı ise environment ve env_file öznitelikleriyle kurulur. İkisi sık karıştırıldığı için yazının ikinci yarısında öncelik sırasını ayrıca ele alıyoruz. .env ve env_file kullanımının temelleri Docker Compose rehberinde anlatıldığı için burada sözdizimi ve öncelik kurallarına odaklanıyoruz. Serinin tamamı için Docker öğrenme rehberi.
İlk örnek: imaj etiketini .env dosyasından almak
Belgelerdeki en basit örnek, imaj etiketini dosyayı düzenlemeden değiştirmektir. Proje klasöründe şu iki dosya olsun:
# uygulama sürümü
TAG=v1.5services:
web:
image: "webapp:${TAG}"Klasörün adı webapp iken docker compose config çıktısı şöyleydi:
docker compose config
name: webapp
services:
web:
image: webapp:v1.5
networks:
default: null
networks:
default:
name: webapp_defaultAynı komutu kabukta değişken tanımlayarak çalıştırdığımızda image: webapp:v2.0, --env-file ./config/.env.prod ile (dosyada TAG=v1.6 varken) image: webapp:v1.6 satırı geldi. Bu üç sonuç, aşağıda anlatacağımız öncelik sırasının pratikteki karşılığıdır.
TAG=v2.0 docker compose config
docker compose --env-file ./config/.env.prod configInterpolasyon sözdizimi

Interpolasyon tırnaksız ve çift tırnaklı değerlere uygulanır; hem süslü parantezli (${VAR}) hem parantezsiz ($VAR) ifadeler desteklenir. Süslü parantezli biçimde aşağıdaki işleçler kullanılabilir. Tablodaki "boş" ifadesi, değişkenin tanımlı ama değerinin boş olduğu durumu anlatır; iki nokta üst üste (:) olan biçimler boş değeri tanımsız gibi kabul eder.
| İfade | Sonuç |
|---|---|
| ${VAR} | VAR değişkeninin değeri |
| ${VAR:-default} | VAR tanımlı ve boş değilse onun değeri, değilse default |
| ${VAR-default} | VAR tanımlıysa (boş olsa bile) onun değeri, değilse default |
| ${VAR:?error} | VAR tanımlı ve boş değilse onun değeri, değilse hata iletisiyle çıkış |
| ${VAR?error} | VAR tanımlıysa onun değeri, değilse hata iletisiyle çıkış |
| ${VAR:+replacement} | VAR tanımlı ve boş değilse replacement, değilse boş |
| ${VAR+replacement} | VAR tanımlıysa replacement, değilse boş |
İfadeler iç içe de yazılabilir: ${VARIABLE:-${FOO}}, ${VARIABLE?$FOO} veya ${VARIABLE:-${FOO:-default}} geçerlidir. Buna karşılık ${VARIABLE/foo/bar} gibi kabuktaki diğer genişletilmiş özellikler Compose'ta desteklenmez. Compose, $ işaretinden sonra gelen metni ancak geçerli bir değişken tanımı oluşturuyorsa işler: ya [_a-zA-Z][_a-zA-Z0-9]* kalıbına uyan bir ad ya da ${ ile başlayan süslü parantezli bir ifade. Diğer durumlarda metin olduğu gibi bırakılır.
Varsayılan, zorunlu ve alternatif değerler
İşleçlerin farkını görmek için şu dosyayı farklı ortamlarla çalıştırdık:
services:
app:
image: "nginx:${NGINX_TAG:-1.27}"
environment:
LOG_LEVEL: ${LOG_LEVEL-info}
LOG_LEVEL_STRICT: ${LOG_LEVEL:-info}
EXTRA: ${FEATURE:+enabled}
DB_HOST: ${DB_HOST:?DB_HOST tanımlanmalı}Önce LOG_LEVEL ve NGINX_TAG değişkenlerini tanımlı ama boş, FEATURE değişkenini dolu verdik. Çıktının ilgili kısmı:
DB_HOST=db LOG_LEVEL= FEATURE=1 NGINX_TAG= docker compose config
name: ornek
services:
app:
environment:
DB_HOST: db
EXTRA: enabled
LOG_LEVEL: ""
LOG_LEVEL_STRICT: info
image: nginx:1.27Farkı burada açıkça görüyoruz: ${LOG_LEVEL-info} boş ama tanımlı değişkeni kabul edip boş değer verdi, ${LOG_LEVEL:-info} ise boş değeri tanımsız sayıp varsayılana döndü. NGINX_TAG boş olduğu için imaj etiketi 1.27 oldu. LOG_LEVEL değişkeni hiç tanımlı değilken iki satır da info, FEATURE yokken de EXTRA boş geldi.
DB_HOST hiç verilmediğinde Compose dosyayı işlemeyi reddetti ve kendi iletimizi gösterdi:
docker compose config
error while interpolating services.app.environment.DB_HOST: required variable DB_HOST is missing a value: DB_HOST tanımlanmalıZorunlu değişkenler, sunucuda eksik bir .env dosyası yüzünden servisin boş parolayla veya yanlış adresle ayağa kalkmasını önlemenin en basit yoludur. Dosyanın hangi değişkenleri kullandığını görmek için --variables bayrağı işe yarar; aynı dosyada çıktı şuydu:
docker compose config --variables
NAME REQUIRED DEFAULT VALUE ALTERNATE VALUE
NGINX_TAG false 1.27
LOG_LEVEL false info
FEATURE false enabled
DB_HOST trueVarsayılanı olmayan bir değişken çözülemezse Compose bir uyarı gösterir ve yerine boş metin koyar. Belgelerdeki örnek bu durumun tehlikesini iyi anlatır: postgres:${POSTGRES_VERSION} ifadesinde değişken tanımlı değilse sonuç postgres: olur ve bu geçerli bir imaj referansı değildir.
Dolar işaretini kaçırmak: $$
Bazı değerlerde Compose'un değil container içindeki kabuğun çözmesi gereken değişkenler bulunur. Tipik örnek PostgreSQL sağlık kontrolüdür. Değişkeni Compose'dan saklamak için çift dolar ($$) yazarsınız; bu bir dolar işaretini harfiyen bırakır ve Compose o ifadeyi interpolasyona sokmaz.
services:
db:
image: postgres:18
environment:
POSTGRES_USER: app
POSTGRES_DB: app
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10sdocker compose config bu dosyayı yazdırırken test satırını yine pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB} olarak gösterdi. Bunun nedeni, komutun çıktısının kendisinin de geçerli bir Compose dosyası olmasıdır: harfiyen dolar işareti çıktıda da kaçırılmış haliyle durur. Sağlık kontrolü container içinde çalışırken ifade kabuk tarafından ${POSTGRES_USER} olarak çözülür.
Anahtarlarda interpolasyon yapılmaz
Interpolasyon yalnızca YAML değerlerine uygulanır, anahtarlara uygulanmaz. Anahtarın kullanıcı tanımlı olduğu birkaç yerde, örneğin labels ve environment içinde, değişkenli bir anahtar istiyorsanız eşittir işaretli liste sözdizimini kullanmalısınız. Şu dosyayı ORTAM=prod ile çalıştırdık:
services:
db:
image: postgres:18
labels:
"com.example.${ORTAM}": "anahtar-interpolasyonu-yok"
web:
image: nginx:latest
labels:
- "com.example.${ORTAM}=liste-sozdizimi"Çıktıda db servisinin etiketi com.example.$${ORTAM} olarak, yani hiç çözülmeden kaldı; web servisinde ise liste sözdizimi sayesinde etiket com.example.prod oldu.
Değişkenler nereden gelir ve hangisi kazanır?

Aynı değişken birden fazla kaynakta tanımlıysa interpolasyon için şu öncelik geçerlidir (yukarıdaki kazanır):
- Kabuk ortamındaki değişkenler.
--env-fileile verilen dosyadaki değişkenler.--env-fileverilmemişse proje dizinindeki.envdosyası. Proje dizini, verilmişse--project-directory, değilse-file verilen ilk Compose dosyasının dizini, o da yoksa kabuğun bulunduğu dizindir.
Birden fazla --env-file verebilirsiniz; Compose dosyaları sırayla okur ve sonraki dosya öncekindeki değeri ezer. --env-file yolu komutu çalıştırdığınız dizine göre çözülür. Var olmayan bir dosya verdiğimizde Compose couldn't find env file iletisi ve dosyanın tam yoluyla hata verip çıktı. Kullanılan değişkenleri ve değerlerini görmek için belgeler docker compose config --environment komutunu önerir.
docker compose --env-file .env --env-file .env.override config
docker compose config --environmentBir ayrıntı daha var: --env-file verilmediğinde Compose iki .env dosyası yükleyebilir. Proje dizinindeki .env dosyası COMPOSE_FILE değişkeniyle başka bir dizindeki Compose dosyasını gösteriyorsa, o dizindeki .env dosyası da daha düşük öncelikle yüklenir. Bu sayede mevcut bir projeyi komut satırına değişken yazmadan kendi değerlerinizle çalıştırabilirsiniz. Ayrıca .env dosyasından yapılan bu yerine koyma bir Docker Compose CLI özelliğidir; Swarm'da docker stack deploy ile çalışırken desteklenmez (bkz. Docker stack deploy).
.env dosyasının sözdizimi
.env dosyasının kuralları basit görünse de tırnak ve yorum kuralları sürpriz yaratabilir. Belgelerdeki kuralların özeti şöyledir: # ile başlayan satırlar ve boş satırlar yok sayılır; her satır bir anahtar ve değer çiftidir; ayırıcı = veya : olabilir; değerin önündeki ve arkasındaki boşluklar atılır. Tırnaksız ve çift tırnaklı değerlere interpolasyon uygulanır, tek tırnaklı değerler harfiyen alınır ve birden fazla satıra yayılabilir. Tırnaksız değerde satır içi yorumun önünde boşluk olmalıdır; tırnaklı değerde yorum kapanış tırnağından sonra gelmelidir. Çift tırnak içinde \n, \t gibi kaçış dizileri desteklenir.
Kuralları denemek için şu .env dosyasını kullandık:
COMPOSE_PROJECT_NAME=blog
DEV_MODE=true
APP_DEBUG=${DEV_MODE:-false}
LITERAL='${DEV_MODE}'
NOT_COMMENT=deger# yorum degil
WITH_COMMENT=deger # bu bir yorum
QUOTED="deger # yorum degil"Bu değişkenleri environment altında kullanan bir servis için docker compose config çıktısı şuydu:
name: blog
services:
app:
environment:
APP_DEBUG: "true"
LITERAL: $${DEV_MODE}
NOT_COMMENT: deger# yorum degil
QUOTED: 'deger # yorum degil'
WITH_COMMENT: deger
image: example/appSonuçlar belgelerle birebir uyuştu. .env içindeki ${DEV_MODE:-false} ifadesi aynı dosyadaki değerle çözüldü; tek tırnaklı değer harfiyen kaldı; boşluksuz # yorum sayılmadı; çift tırnak içindeki # değerin parçası oldu. .env içindeki COMPOSE_PROJECT_NAME da proje adını blog yaptı. Aynı klasörde COMPOSE_DISABLE_ENV_FILE=1 ile çalıştırdığımızda .env dosyası okunmadı, her değişken için The "APP_DEBUG" variable is not set. Defaulting to a blank string. biçiminde uyarılar geldi ve proje adı klasör adına döndü.
Container ortamında öncelik sırası

Interpolasyon dosyayı çözdükten sonra container'ın ortamı ayrı bir öncelik kuralıyla kurulur. Belgelerdeki sıra (yukarıdaki kazanır) şöyledir:
docker compose run -eile komut satırında verilen değer.environmentveyaenv_fileiçinde olup değeri kabuktan ya da bir ortam dosyasından interpolasyonla gelen değer.- Yalnızca
environmentözniteliğiyle verilen değer. env_fileözniteliğiyle verilen değer.- İmajdaki
ENVtalimatıyla gelen değer. Dockerfile'dakiARGveyaENVancak Compose tarafındaenvironment,env_fileya darun --envgirdisi yoksa etkili olur.
Belgelerdeki örneği doğruladık: webapp.env dosyasında NODE_ENV=test, environment altında NODE_ENV=production varken docker compose config servis ortamını tek satır olarak NODE_ENV: production gösterdi; yani environment kazandı. Ayrıca kabuk ortamı ve .env dosyası, Compose dosyasında karşılığı olmadıkça container'a kendiliğinden bir değişken eklemez. environment altında yalnızca - DEBUG yazarsanız değer kabuktan geçirilir ve tanımsızsa uyarı verilmez; - DEBUG=${DEBUG} yazarsanız değişken kabukta veya .env dosyasında yoksa Compose uyarır. Ortam değişkenlerinin ARG ile ilişkisi için ARG ve ENV farkı yazısına bakın.
COMPOSE_ ile başlayan önceden tanımlı değişkenler
Compose kendi davranışını da ortam değişkenleriyle ayarlamanıza izin verir. Bunlar .env dosyasına, kabuğa veya komut satırına yazılabilir. Sunucuda en çok işe yarayanlar şunlardır:
| Değişken | Ne yapar |
|---|---|
| COMPOSE_PROJECT_NAME | Proje adını belirler; container adları proje ve servis adından oluşur (myapp-web-1 gibi) |
| COMPOSE_FILE | Kullanılacak Compose dosyaları; Linux ve macOS'ta iki nokta, Windows'ta noktalı virgülle ayrılır |
| COMPOSE_PATH_SEPARATOR | COMPOSE_FILE için farklı bir ayırıcı |
| COMPOSE_PROFILES | up sırasında etkinleştirilecek profiller, virgülle ayrılır |
| COMPOSE_ENV_FILES | --env-file verilmediğinde kullanılacak ortam dosyaları, virgülle ayrılır |
| COMPOSE_DISABLE_ENV_FILE | true veya 1 ise varsayılan .env dosyası yok sayılır |
| COMPOSE_REMOVE_ORPHANS | Artık dosyada olmayan servislerin container'larını otomatik kaldırır |
| COMPOSE_IGNORE_ORPHANS | Sahipsiz container tespitini kapatır |
| COMPOSE_PROGRESS | İlerleme çıktısının türü: auto, tty, plain, json, quiet |
Proje adı için öncelik sırası şöyledir: -p bayrağı, COMPOSE_PROJECT_NAME, Compose dosyasındaki en üst düzey name: (birden fazla -f varsa sonuncusu), proje dizininin adı ve son olarak bulunduğunuz dizinin adı. Proje adları yalnızca küçük harf, rakam, tire ve alt çizgi içerebilir ve küçük harf ya da rakamla başlamalıdır; klasör adınız bu kurala uymuyorsa diğer yollardan birini kullanmanız gerekir. Belgeler ayrıca COMPOSE_API_VERSION, COMPOSE_HTTP_TIMEOUT gibi bazı eski değişkenlerin Compose V2'de etkisi olmadığını belirtir.
Interpolasyonun ne zaman çalıştığı da önemlidir. Belirtime göre interpolasyon, birden fazla dosya birleştirilmeden önce her dosyaya ayrı ayrı uygulanır. YAML anchor ve alias çözümlemesi ise interpolasyondan önce yapılır; bu yüzden anchor veya alias adlarını değişkenle belirleyemezsiniz. Dosya birleştirme ve fragment kullanımı include, extends ve merge yazısında anlatılıyor.
Sık yapılan hatalar
- Varsayılansız değişkene güvenmek. Tanımsız değişken boş metne dönüşür ve
postgres:gibi geçersiz değerler oluşur. Kritik değerlerde:?kullanın. - :- ile - farkını gözden kaçırmak. Boş bırakılmış bir değişken
-biçiminde boş değer olarak geçer. - Container içi değişkeni $ ile yazmak. Compose onu kendi ortamından çözmeye çalışır; container'ın çözmesi gerekiyorsa
$$yazın. - Anahtarda değişken kullanmak. Anahtarlar çözülmez;
labelsveenvironmentiçin liste sözdizimini kullanın. - .env dosyasını yanlış dizine koymak.
-file başka bir dizindeki dosyayı verdiğinizde proje dizini o dosyanın dizinidir ve.envorada aranır. - Kabukta kalmış eski bir değişken. Kabuk ortamı
.envdosyasını ezer; beklenmeyen bir değer görüyorsanız önce kabuktaki değişkenleri kontrol edin.
Sık Sorulan Sorular
.env dosyası container'a otomatik olarak geçer mi?
Hayır. .env dosyası Compose dosyasının interpolasyonu ve Compose'un kendi ayarları içindir. Bir değerin container ortamına girmesi için environment veya env_file ile açıkça verilmesi gerekir.
Compose dosyasının gerçekte hangi değerlerle çözüldüğünü nasıl görürüm?
docker compose config çözülmüş modeli yazdırır, --variables dosyadaki değişkenleri ve varsayılanlarını, --environment ise interpolasyon için kullanılan ortamı gösterir.
Farklı ortamlar için farklı .env dosyaları nasıl kullanılır?
Dosyaları .env.prod, .env.test gibi adlandırıp --env-file ile seçebilir ya da COMPOSE_ENV_FILES değişkenine yazabilirsiniz. Belgelerin en iyi uygulama sayfası da ortamlar için ayrı dosyalar kullanmayı önerir.
${VAR/foo/bar} gibi kabuk değiştirmeleri çalışır mı?
Hayır. Compose yalnızca tablodaki varsayılan, zorunlu ve alternatif değer biçimlerini ve bunların iç içe kullanımını destekler.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Docker öğrenme rehberi · Docker Compose rehberi · Compose secrets ve configs · Compose include, extends ve merge · ARG ve ENV farkı