Docker Compose'ta parola, API anahtarı veya sertifika gibi gizli bilgileri container'a vermenin önerilen yolu secrets özelliğidir: sırrı dosyanın en üst düzeyindeki secrets bölümünde tanımlarsınız, ona ihtiyaç duyan servise de servis altındaki secrets listesiyle erişim verirsiniz. Compose sırrı container içinde /run/secrets/<secret_name> yolunda bir dosya olarak sunar. Gizli olmayan yapılandırma dosyaları için aynı mantıkla çalışan configs özelliği vardır; imajı yeniden derlemeden servisin davranışını değiştirmenizi sağlar.
Bu yazı Compose dosyasındaki secrets ve configs öğelerini, kısa ve uzun sözdizimlerini, kaynak türlerini ve sık yapılan hataları anlatır. İmaj derlenirken kullanılan sırlar (RUN --mount=type=secret) ayrı bir konudur ve Docker build secrets yazısında anlatılır; Swarm üzerinde docker stack deploy ile çalışan sırlar için Docker stack deploy yazısına bakın. Serinin tamamı için Docker öğrenme rehberi sayfasına göz atabilirsiniz.
Neden ortam değişkeni yerine secret?

Docker belgeleri sırrı, ağ üzerinden taşınmaması, Dockerfile içinde veya uygulamanın kaynak kodunda şifrelenmeden saklanmaması gereken her türlü veri olarak tanımlar: parolalar, sertifikalar, API anahtarları. Bu tür verileri environment ile container'a vermek kolaydır ama belgeler üç risk sayar. Ortam değişkenleri çoğu zaman tüm süreçlere açıktır, kimin eriştiğini izlemek zordur ve hata ayıklarken farkında olmadan loglara yazılabilir. Secret kullanmak bu riskleri azaltır.
Compose'un ortam değişkeni belgesi de aynı yönde bir ipucu verir: parola gibi hassas bilgileri ortam değişkenleriyle container'a geçirmeyin, secret kullanın. Ortam değişkenlerinin nasıl çözümlendiğini ve öncelik sırasını Compose değişken interpolasyonu yazısında bulabilirsiniz.
| Yöntem | Container içinde görünüşü | Uygun olduğu veri |
|---|---|---|
| environment | Süreç ortam değişkeni | Hassas olmayan ayarlar (LOG_LEVEL, TZ) |
| secrets | /run/secrets altında salt okunur dosya | Parola, token, sertifika, API anahtarı |
| configs | Varsayılan olarak kök dizinde config adıyla dosya | nginx.conf, uygulama ayar dosyası |
İki adımda secret kullanmak
Bir sırrı container'a ulaştırmak iki adımlı bir iştir. Önce en üst düzeydeki secrets öğesinde sırrı tanımlarsınız. Ardından sırra ihtiyaç duyan her servisin altına secrets özniteliğini yazarsınız. Compose erişimi servis bazında verir: belirtime göre bir sırrı en üst düzeyde tanımlamak, hiçbir servise kendiliğinden erişim vermez; erişim her serviste açıkça yazılmalıdır. Belgeler bu yöntemin, container içinde standart dosya sistemi izinleriyle ayrıntılı erişim denetimine de olanak verdiğini vurgular.
services:
app:
image: myapp:latest
secrets:
- api_key
secrets:
api_key:
file: ./api_key.txtBu dosyada app container'ı içinde /run/secrets/api_key yolunda, içeriği host'taki ./api_key.txt dosyasıyla aynı olan bir dosya bulunur. Kısa sözdiziminde kaynak adı ile container içindeki dosya adı aynıdır ve dosya salt okunur bağlanır. Uygulamanız sırrı ortam değişkeninden değil bu dosyadan okumalıdır.
Servis tarafında tanımsız bir sırra başvurursanız Compose dosyayı reddeder. En üst düzey secrets bölümünü sildiğimiz denemede Compose v5.5.1 şu hatayı verdi:
docker compose config --quiet
service "app" refers to undefined secret api_key: invalid compose projectSecret'lar yalnızca Linux container'larında desteklenir. Belgelerin açıklamasına göre Compose her sırrı tek bir dosyayı bind mount ile bağlayarak teslim eder; Windows container'ları ise yalnızca dizin bağlamayı destekler.
Kaynak türleri: file ve environment
En üst düzey secrets bildirimindeki kaynak iki türden biridir. file ile sır, verdiğiniz yoldaki dosyanın içeriğinden oluşturulur. environment ile sır, host'taki bir ortam değişkeninin değerinden oluşturulur. Belgeler environment kaynağının yalnızca Docker Compose tarafından desteklendiğini, docker stack deploy ile dağıtımda desteklenmediğini belirtir; Swarm için file veya external kullanılmalıdır.
Uygulama dağıtıldığında sırrın platformdaki adı proje adıyla öneklenir. Belirtimdeki örnekte server-certificate adlı sır, <project_name>_server-certificate adıyla kaydedilir. Proje adının nasıl belirlendiğini interpolasyon yazısındaki COMPOSE_PROJECT_NAME bölümünde bulabilirsiniz.
Çok servisli örnek: _FILE ortam değişkenleri
Belgelerdeki WordPress ve MySQL örneği, sırların servisler arasında nasıl paylaşıldığını ve parolaların ortam değişkenine hiç yazılmadan nasıl verildiğini gösterir. Aşağıdaki uyarlamada WordPress portu yalnızca yerel adrese yayınlanır:
services:
db:
image: mysql:latest
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_root_password
- db_password
wordpress:
image: wordpress:latest
depends_on:
- db
ports:
- "127.0.0.1:8000:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./db_password.txt
db_root_password:
file: ./db_root_password.txt
volumes:
db_data:Burada dikkat edilecek üç nokta var. Birincisi, db servisi iki sırra da erişirken wordpress servisi yalnızca db_password sırrına erişir; root parolası WordPress container'ına hiç girmez. İkincisi, ortam değişkenlerinde parolanın kendisi değil, sır dosyasının yolu vardır. _FILE ile biten bu değişkenler, belgelerin deyişiyle bazı imajların izlediği bir kuraldır; mysql ve postgres gibi Docker Official Images bu kuralı destekler. Kullandığınız imajın bunu destekleyip desteklemediğini imajın kendi belgesinden kontrol edin. Üçüncüsü, her container için Docker /run/secrets/<secret_name> altında ilgili değerle bir bind mount oluşturur.
Veritabanının hazır olmasını beklemek için yalnızca depends_on listesi yetmez; sağlık kontrolüyle bekleme ve başlangıç sırası init container ve lifecycle hook yazısında ele alınıyor.
Uzun sözdizimi: target, uid, gid ve mode

Uzun sözdizimi, sırrın container içinde nasıl oluşturulacağını daha ayrıntılı belirlemenizi sağlar. Alanlar şunlardır:
source: Sırrın platformdaki adı.target:/run/secrets/altında oluşturulacak dosyanın adı; farklı bir konum gerekiyorsa mutlak yol. Verilmezsesourceile aynıdır.uidvegid: Dosyanın sahibi olacak sayısal kullanıcı ve grup kimliği.mode: Sekizlik gösterimde dosya izinleri. Varsayılan herkesin okuyabildiği0444değeridir; yazma biti ayarlansa da yok sayılır, çalıştırma biti ayarlanabilir.
Aşağıdaki örnekte sır host'taki OAUTH_TOKEN değişkeninden okunur, container içinde /run/secrets/token adıyla, 103 numaralı kullanıcı ve gruba ait ve yalnızca sahibi ile grubun okuyabileceği izinle oluşturulur:
services:
worker:
image: example/worker
user: "103:103"
secrets:
- source: oauth_token
target: token
uid: "103"
gid: "103"
mode: 0o440
secrets:
oauth_token:
environment: "OAUTH_TOKEN"docker compose config bu dosyayı normalize ettiğinde sır tanımı şu hale geldi; proje adı bu denemede klasör adı olan s3 idi. Sırrın platform adının proje adıyla öneklendiğini burada görebilirsiniz:
secrets:
oauth_token:
name: s3_oauth_token
environment: OAUTH_TOKENAynı çıktıda servis tarafındaki mode değeri "0440" olarak yazıldı. YAML'da 0o440 biçimi sekizlik sayıyı açıkça belirtir; belirtimdeki configs örneklerinde 0440 yazımı da kullanılır.
Build sırasında Compose secret kullanmak
Sırlar yalnızca çalışma zamanında değil, imaj derlenirken de gerekebilir; örneğin özel bir npm deposundan paket indirmek için bir token. Compose'ta bunun için sır build bölümünün altında listelenir. Belgelerdeki örnekte npm_token sırrı derleme sırasında kullanılabilir hale gelir ve değeri NPM_TOKEN ortam değişkeninden alınır:
services:
myapp:
build:
context: .
secrets:
- npm_token
secrets:
npm_token:
environment: NPM_TOKENDockerfile tarafında sırrın RUN --mount=type=secret ile nasıl okunduğu ve neden ARG veya ENV ile sır verilmemesi gerektiği Docker build secrets yazısının konusudur.
Configs: yapılandırma dosyalarını imaj dışında tutmak

configs, servislerin davranışını imajı yeniden derlemeden uyarlamanızı sağlar. Belirtim sırları, hassas veriye odaklanan ve buna göre ek kısıtları olan bir config türü olarak tanımlar; yani iki özellik aynı ailedendir. Servisler config'lere de yalnızca servis altında configs özniteliğiyle açıkça erişim verildiğinde ulaşır. Varsayılan olarak config dosyası container komutunu çalıştıran kullanıcıya aittir ve herkesin okuyabildiği 0444 izniyle bağlanır; ikisi de servis yapılandırmasıyla değiştirilebilir.
Config kaynağı dört türden biridir:
file: İçerik, verilen yoldaki dosyadan alınır.environment: İçerik bir ortam değişkeninin değeridir. Belgeye göre Docker Compose 2.23.1 ile geldi.content: İçerik dosyanın içine satır içi yazılır ve Compose değişkenleri interpolasyonla çözer. Bu da 2.23.1 ile geldi.external:trueise config'in önceden oluşturulduğunu belirtir; Compose onu oluşturmaya çalışmaz, yoksa hata verir.namealanıyla platformda aranacak adı verebilirsiniz; bu ad proje adıyla öneklenmez, olduğu gibi kullanılır.
Kısa sözdiziminde yalnızca config adı yazılır ve dosya Linux container'larında varsayılan olarak /<config_name> yoluna bağlanır. Uzun sözdizimi sırlardaki gibi source, target, uid, gid ve mode alanlarını kabul eder; target verilmezse yol /<source> olur. Aşağıdaki örnekte nginx yapılandırması dosyadan, uygulama ayarları ise satır içi içerikten gelir:
name: magaza
services:
proxy:
image: nginx:latest
configs:
- source: nginx_conf
target: /etc/nginx/conf.d/default.conf
api:
image: example/api
configs:
- app_config
configs:
nginx_conf:
file: ./nginx.conf
app_config:
content: |
debug=${DEBUG}
app.name=${COMPOSE_PROJECT_NAME}Proje klasöründeki .env dosyasında DEBUG=false varken docker compose config çıktısındaki app_config bölümü şöyleydi:
app_config:
name: magaza_app_config
content: |
debug=false
app.name=magazaÇıktı iki şeyi gösterir: content içindeki değişkenler Compose tarafından çözüldü ve COMPOSE_PROJECT_NAME en üst düzeydeki name değerini aldı; config'in platform adı da proje adıyla öneklendi. Aynı komutu kabukta DEBUG=true ile çalıştırdığımızda satır debug=true oldu, çünkü kabuk değişkeni .env dosyasından önce gelir.
Belirtim external: true olduğunda name dışındaki tüm alanların anlamsız olduğunu ve Compose'un başka bir alan görürse dosyayı geçersiz sayarak reddettiğini söyler. Bizim denememizde external: true ile birlikte file yazılmış bir config, Compose v5.5.1'de docker compose config --quiet aşamasında hata vermedi. Bu yüzden doğrulamanın geçmesine güvenmeyin; external tanımlarda yalnızca external ve gerekiyorsa name yazın.
Config izinlerini uzun sözdizimiyle daraltmak
Bir servise birden fazla config verebilir, kısa ve uzun sözdizimini aynı listede karıştırabilirsiniz. Servis tanımında geçen bir config ne platformda ne de en üst düzey configs bölümünde yoksa Compose hata bildirir. Belgelerdeki Redis örneği uzun sözdiziminin tipik kullanımını gösterir: config container içinde /redis_config adıyla, 103 numaralı kullanıcı ve gruba ait, yalnızca sahibi ve grubun okuyabileceği 0440 izniyle bağlanır. En üst düzeyde tanımlı olan ikinci config ise servise listelenmediği için o container'a hiç girmez.
services:
redis:
image: redis:latest
configs:
- source: my_config
target: /redis_config
uid: "103"
gid: "103"
mode: 0440
configs:
my_config:
external: true
my_other_config:
external: trueBu örnekteki iki config de external olarak tanımlı; yani platformda önceden oluşturulmuş olmaları beklenir ve yoksa dağıtım başarısız olur. Tek sunucuda çalışırken genellikle file veya content kaynağı daha pratiktir, çünkü içerik doğrudan proje klasöründen veya Compose dosyasından gelir.
Birden fazla Compose dosyasını birleştirirken sırlar ve config'ler için özel bir kural geçerlidir. Belirtimin birleştirme kurallarına göre servis altındaki secrets ve configs listeleri sıradan diziler gibi sona eklenmez; benzersiz anahtar olarak target kullanılır. Override dosyası aynı hedef yola sahip bir girdi tanımlarsa bu girdi yenisiyle birleşir, farklı hedefli girdiler ise listeye eklenir. Birleştirme kurallarının tamamı include, extends ve merge yazısında anlatılıyor.
Sık yapılan hatalar
- Sırrı tanımlayıp servise vermemek. En üst düzeyde tanım erişim vermez; servis altında
secretslistesi gerekir. - Parolayı yine environment ile vermek. Sırrı tanımlayıp aynı değeri ortam değişkenine de yazarsanız secret kullanmanın faydası kaybolur. İmaj destekliyorsa
_FILEdeğişkenlerini kullanın. - Dosya kaynaklı sırda mode ve uid beklemek. Bu alanlar yalnızca
environmentkaynağında uygulanır. - Stack deploy ile environment kaynağı kullanmak. Swarm bu kaynağı desteklemez;
fileveyaexternalkullanın. - Sır dosyasını kaynak koduyla birlikte saklamak. Belgelerin sır tanımı, bu verinin kaynak kodunda şifrelenmeden tutulmamasını içerir; sır dosyalarını uygulama deposunun dışında tutun.
- Config içeriğini değiştirip imajı yeniden derlemek. Config'in amacı tam tersidir: yapılandırmayı imajdan ayırmak.
Sık Sorulan Sorular
Compose secret dosyası container içinde nerede bulunur?
Kısa sözdiziminde /run/secrets/<secret_name> yolunda, salt okunur olarak. Uzun sözdiziminde target ile /run/secrets/ altındaki dosya adını veya mutlak bir yol verebilirsiniz.
Secrets ile configs arasındaki fark nedir?
İkisi de dosya olarak bağlanır ve servis bazında açık izin ister. Secrets hassas veriye özeldir ve /run/secrets/ altında sunulur; configs ise gizli olmayan yapılandırma içindir, varsayılan olarak kök dizinde config adıyla bağlanır ve content ile satır içi, interpolasyonlu içerik alabilir.
Secret kullanmak Windows container'larında çalışır mı?
Belgelere göre hayır. Secret'lar yalnızca Linux container'larında desteklenir, çünkü Compose her sırrı tek dosyalık bir bind mount ile verir ve Windows container'ları yalnızca dizin bağlamayı destekler.
Build sırasında gereken token için ne kullanmalıyım?
Compose'ta sırrı build.secrets altında listeleyin ve Dockerfile'da RUN --mount=type=secret ile okuyun. Ayrıntılar build secrets yazısında.
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 build secrets · Compose değişken interpolasyonu · Docker stack deploy · Docker Compose rehberi · VPS güvenlik sertleştirme