{"id":617,"date":"2026-10-03T12:00:00","date_gmt":"2026-10-03T12:00:00","guid":{"rendered":"https:\/\/konteynerium.com\/index.php\/2026\/10\/03\/docker-secrets-gizli-bilgi-yonetimi-build-ve-runtime\/"},"modified":"2026-10-03T12:00:00","modified_gmt":"2026-10-03T12:00:00","slug":"docker-secrets-gizli-bilgi-yonetimi-build-ve-runtime","status":"publish","type":"post","link":"https:\/\/konteynerium.com\/index.php\/2026\/10\/03\/docker-secrets-gizli-bilgi-yonetimi-build-ve-runtime\/","title":{"rendered":"Gizli Bilgi Y\u00f6netimi: Build Secrets ve Compose Secrets"},"content":{"rendered":"<p>Parolalar, API anahtarlar\u0131 ve token&#8217;lar&#8230; Container d\u00fcnyas\u0131nda bunlar\u0131 yanl\u0131\u015f yere koyman\u0131n en kolay yolu <code>ENV<\/code> ya da <code>ARG<\/code> kullanmakt\u0131r, ve en tehlikeli yolu da budur. Bu yaz\u0131da \u00f6nce neden tehlikeli oldu\u011funu ger\u00e7ek bir deneyle g\u00f6r\u00fcyor, sonra gizli bilgiyi <strong>build s\u0131ras\u0131nda<\/strong> (BuildKit secret mount) ve <strong>\u00e7al\u0131\u015fma s\u0131ras\u0131nda<\/strong> (Compose secrets) g\u00fcvenle nas\u0131l kullanaca\u011f\u0131n\u0131z\u0131 \u00f6\u011freniyoruz.<\/p>\n<h2>Neden <code>ARG<\/code> ve <code>ENV<\/code> g\u00fcvenli de\u011fil?<\/h2>\n<p>Docker dok\u00fcmantasyonu bunu a\u00e7\u0131k\u00e7a belirtir: build arg\u00fcmanlar\u0131 ve ortam de\u011fi\u015fkenleri, nihai imajda kal\u0131c\u0131 olarak sakland\u0131klar\u0131 i\u00e7in gizli bilgi aktarmaya uygun de\u011fildir. Bunu do\u011frulamak i\u00e7in \u015fu Dockerfile&#8217;\u0131 build ettik:<\/p>\n<pre><code>FROM temel-imaj\nARG API_TOKEN\nENV TOKEN_ENV=$API_TOKEN\nRUN echo \"kuruldu\"\n\n$ docker build --build-arg API_TOKEN=s3cr3t-token-123 -t sec:bad .<\/code><\/pre>\n<p>\u0130maj\u0131 inceleyen herkes \u2014 imaj\u0131 \u00e7ekebilen herkes \u2014 token&#8217;\u0131 g\u00f6rebilir:<\/p>\n<pre><code>$ docker history --no-trunc sec:bad --format '{{.CreatedBy}}' | grep TOKEN\nRUN |1 API_TOKEN=s3cr3t-token-123 \/bin\/sh -c echo \"kuruldu\" # buildkit\nENV TOKEN_ENV=s3cr3t-token-123\nARG API_TOKEN=s3cr3t-token-123\n\n$ docker inspect sec:bad --format '{{.Config.Env}}'\n[PATH=... TOKEN_ENV=s3cr3t-token-123]<\/code><\/pre>\n<p>Token hem katman ge\u00e7mi\u015finde hem de imaj\u0131n yap\u0131land\u0131rmas\u0131nda duruyor. \u0130maj\u0131 <code>ENV<\/code> olmadan, yaln\u0131zca <code>ARG<\/code> ile build etseniz bile de\u011fer katman ge\u00e7mi\u015finde kal\u0131r. Modern Docker bunu build s\u0131ras\u0131nda da uyar\u0131r:<\/p>\n<pre><code>WARN: SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions\nfor sensitive data (ARG \"API_TOKEN\") (line 2)<\/code><\/pre>\n<h2>Build s\u0131ras\u0131nda: BuildKit secret mount<\/h2>\n<p>\u00c7\u00f6z\u00fcm, s\u0131rr\u0131 imaja <em>hi\u00e7 yazmadan<\/em>, yaln\u0131zca ihtiya\u00e7 duyan <code>RUN<\/code> komutuna ge\u00e7ici olarak ba\u011flamakt\u0131r:<\/p>\n<pre><code>FROM temel-imaj\nRUN --mount=type=secret,id=api_token \\\n    TOKEN=$(cat \/run\/secrets\/api_token) &amp;&amp; ozel-paketi-indir \"$TOKEN\"<\/code><\/pre>\n<pre><code># Dosyadan\ndocker build --secret id=api_token,src=token.txt .\n\n# Ortam de\u011fi\u015fkeninden\ndocker build --secret id=api_token,env=API_TOKEN .<\/code><\/pre>\n<p>S\u0131r varsay\u0131lan olarak <code>\/run\/secrets\/&lt;id&gt;<\/code> yoluna yaln\u0131zca o <code>RUN<\/code> ad\u0131m\u0131 s\u00fcresince ba\u011flan\u0131r. Ba\u015fka bir hedef yol (<code>target=<\/code>) ya da ortam de\u011fi\u015fkeni olarak (<code>env=<\/code>) ba\u011flamak da m\u00fcmk\u00fcnd\u00fcr:<\/p>\n<pre><code>RUN --mount=type=secret,id=aws,target=\/root\/.aws\/credentials aws s3 cp ...\nRUN --mount=type=secret,id=aws-key-id,env=AWS_ACCESS_KEY_ID aws s3 cp ...<\/code><\/pre>\n<p>Do\u011frulama denemesinde 16 karakterlik bir token&#8217;\u0131 bu y\u00f6ntemle okuttuk ve ad\u0131m\u0131n \u00e7\u0131kt\u0131s\u0131nda yaln\u0131zca uzunlu\u011fu yazd\u0131rd\u0131k. Ard\u0131ndan imaj\u0131n i\u00e7inde ve katman ge\u00e7mi\u015finde token&#8217;\u0131 arad\u0131k:<\/p>\n<pre><code>$ docker run --rm sec:ok ls \/run\/secrets\nls: cannot access '\/run\/secrets': No such file or directory\n\n$ docker history --no-trunc sec:ok | grep -c s3cr3t\n0\n$ docker save sec:ok | tar -xO | grep -c s3cr3t\n0<\/code><\/pre>\n<p>S\u0131r nihai imajda yok: <code>\/run\/secrets<\/code> dizini mevcut de\u011fil, ge\u00e7mi\u015fte ve kaydedilmi\u015f imaj ar\u015fivinde hi\u00e7 e\u015fle\u015fme bulunmad\u0131. \u00d6zel bir Git deposuna eri\u015fim gibi durumlar i\u00e7in benzer \u015fekilde <code>RUN --mount=type=ssh<\/code> ve <code>docker buildx build --ssh default .<\/code> kullan\u0131labilir.<\/p>\n<div class=\"callout\">\n  <span class=\"glyph\">!<\/span><\/p>\n<p>S\u0131rr\u0131 g\u00fcvenle ba\u011flasan\u0131z bile, komutunuzun kendisi s\u0131rr\u0131 bir dosyaya yazarsa, \u00e7\u0131kt\u0131ya basarsa ya da yan etki olarak imaja kaydederse yine s\u0131zar. Secret mount, s\u0131rr\u0131 <em>katmana yaz\u0131lmaktan<\/em> korur, komutun kendi davran\u0131\u015f\u0131ndan de\u011fil.<\/p>\n<\/div>\n<h2>\u00c7al\u0131\u015fma s\u0131ras\u0131nda: Compose secrets<\/h2>\n<p>\u00c7al\u0131\u015fan container i\u00e7in gizli bilgiler, ortam de\u011fi\u015fkeni yerine bir dosya olarak ba\u011flanmal\u0131d\u0131r. Compose&#8217;ta <code>secrets<\/code> b\u00f6l\u00fcm\u00fc bunu yapar; container i\u00e7inde <code>\/run\/secrets\/&lt;ad&gt;<\/code> alt\u0131nda salt okunur bir dosya olarak g\u00f6r\u00fcn\u00fcr:<\/p>\n<pre><code>services:\n  db:\n    image: postgres:18\n    environment:\n      POSTGRES_PASSWORD_FILE: \/run\/secrets\/db_parola\n    secrets:\n      - db_parola\n\nsecrets:\n  db_parola:\n    file: .\/secrets\/db_parola.txt<\/code><\/pre>\n<p>Bir\u00e7ok resmi imaj (PostgreSQL, MySQL, MariaDB gibi) bu yakla\u015f\u0131m i\u00e7in <code>*_FILE<\/code> ortam de\u011fi\u015fkenlerini destekler: parola de\u011fi\u015fkenin kendisinde de\u011fil, g\u00f6sterdi\u011fi dosyada durur. B\u00f6ylece <code>docker inspect<\/code> \u00e7\u0131kt\u0131s\u0131nda ve s\u00fcre\u00e7 ortam\u0131nda d\u00fcz metin parola g\u00f6r\u00fcnmez.<\/p>\n<table>\n<thead>\n<tr>\n<th>Y\u00f6ntem<\/th>\n<th>\u0130maja s\u0131zar m\u0131?<\/th>\n<th><code>docker inspect<\/code>&#8216;te g\u00f6r\u00fcn\u00fcr m\u00fc?<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>ARG<\/code> \/ <code>ENV<\/code> (build)<\/td>\n<td><strong>Evet<\/strong><\/td>\n<td><strong>Evet<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>docker run -e PAROLA=...<\/code><\/td>\n<td>Hay\u0131r<\/td>\n<td><strong>Evet<\/strong> (<code>Config.Env<\/code>)<\/td>\n<\/tr>\n<tr>\n<td>BuildKit secret mount<\/td>\n<td>Hay\u0131r<\/td>\n<td>Yok (yaln\u0131zca build&#8217;de)<\/td>\n<\/tr>\n<tr>\n<td>Compose secrets (dosya)<\/td>\n<td>Hay\u0131r<\/td>\n<td>Hay\u0131r \u2014 dosya olarak ba\u011flan\u0131r<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>\u00dcretim i\u00e7in notlar<\/h2>\n<ul>\n<li><strong>S\u0131r dosyalar\u0131n\u0131 Git&#8217;e koymay\u0131n.<\/strong> <code>secrets\/<\/code> klas\u00f6r\u00fcn\u00fc <code>.gitignore<\/code> ve <a href=\"https:\/\/konteynerium.com\/index.php\/2026\/09\/30\/dockerignore-ve-build-baglami-docker-build-neden-yavas\/\">.dockerignore<\/a> i\u00e7ine ekleyin.<\/li>\n<li><strong>S\u0131zan s\u0131rr\u0131 yenileyin.<\/strong> Bir token imaja ya da repoya girdiyse silmek yetmez; iptal edip yenisini \u00fcretin \u2014 ge\u00e7mi\u015fte kalm\u0131\u015f olabilir.<\/li>\n<li><strong>Daha b\u00fcy\u00fck sistemlerde<\/strong> Docker Swarm secrets, Kubernetes Secrets ya da bir gizli bilgi y\u00f6neticisi (HashiCorp Vault, bulut sa\u011flay\u0131c\u0131 KMS\/Secrets Manager) kullan\u0131n. Swarm taraf\u0131 i\u00e7in <a href=\"https:\/\/konteynerium.com\/index.php\/2026\/06\/12\/docker-swarm-nedir-coklu-sunucuda-container-orkestrasyonu\/\">Docker Swarm<\/a> yaz\u0131s\u0131na bak\u0131n.<\/li>\n<li><strong>CI&#8217;da<\/strong> s\u0131rlar\u0131 pipeline&#8217;\u0131n gizli depolama \u00f6zelli\u011finden verin ve <code>--secret id=...,env=...<\/code> ile build&#8217;e aktar\u0131n (bkz. <a href=\"https:\/\/konteynerium.com\/index.php\/2026\/08\/14\/cicd-ile-docker-github-actions-otomatik-build-deploy\/\">CI\/CD ile Docker<\/a>).<\/li>\n<\/ul>\n<h2>H\u0131zl\u0131 kontrol listesi<\/h2>\n<ul>\n<li>Dockerfile&#8217;da <code>ARG<\/code>\/<code>ENV<\/code> ile parola, token ya da anahtar var m\u0131? (Varsa kald\u0131r\u0131n.)<\/li>\n<li>Build&#8217;de ihtiya\u00e7 duyulan s\u0131rlar <code>RUN --mount=type=secret<\/code> ile mi veriliyor?<\/li>\n<li>\u00c7al\u0131\u015fan servisler parolay\u0131 dosya (<code>secrets<\/code>, <code>*_FILE<\/code>) olarak m\u0131 al\u0131yor?<\/li>\n<li><code>docker history --no-trunc<\/code> \u00e7\u0131kt\u0131s\u0131nda hassas bir \u015fey g\u00f6r\u00fcn\u00fcyor mu?<\/li>\n<\/ul>\n<p>\u0130maj g\u00fcvenli\u011finin geni\u015f \u00e7er\u00e7evesi i\u00e7in <a href=\"https:\/\/konteynerium.com\/index.php\/2026\/07\/03\/container-image-guvenligi-zafiyet-taramasi-en-iyi-uygulamalar\/\">Container Image G\u00fcvenli\u011fi<\/a> yaz\u0131s\u0131na ve sitemizdeki <a href=\"https:\/\/konteynerium.com\/index.php\/container-guvenlik-sertlestirme-merkezi\/\">G\u00fcvenlik Merkezi<\/a> arac\u0131na bak\u0131n.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Parola ve token&#8217;lar\u0131 ARG ya da ENV ile vermek neden tehlikeli? S\u0131z\u0131nt\u0131y\u0131 ger\u00e7ek bir deneyle g\u00f6sterip BuildKit secret mount ve Compose secrets ile gizli bilgiyi g\u00fcvenle kullanmay\u0131 \u00f6\u011frenin.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"seviye":[9],"class_list":["post-617","post","type-post","status-publish","format-standard","hentry","category-orkestrasyon-guvenlik","seviye-ileri"],"_links":{"self":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts\/617","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/comments?post=617"}],"version-history":[{"count":0,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts\/617\/revisions"}],"wp:attachment":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/media?parent=617"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/categories?post=617"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/tags?post=617"},{"taxonomy":"seviye","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/seviye?post=617"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}