{"id":614,"date":"2026-10-02T12:00:00","date_gmt":"2026-10-02T12:00:00","guid":{"rendered":"https:\/\/konteynerium.com\/index.php\/2026\/10\/02\/multi-stage-build-ile-kucuk-imajlar\/"},"modified":"2026-10-02T12:00:00","modified_gmt":"2026-10-02T12:00:00","slug":"multi-stage-build-ile-kucuk-imajlar","status":"publish","type":"post","link":"https:\/\/konteynerium.com\/index.php\/2026\/10\/02\/multi-stage-build-ile-kucuk-imajlar\/","title":{"rendered":"Multi-Stage Build ile K\u00fc\u00e7\u00fck ve G\u00fcvenli \u0130majlar"},"content":{"rendered":"<p>Bir uygulamay\u0131 derlemek i\u00e7in gereken ara\u00e7lar (derleyici, geli\u015ftirme k\u00fct\u00fcphaneleri, test ara\u00e7lar\u0131) \u00e7al\u0131\u015ft\u0131rmak i\u00e7in gerekenlerden \u00e7ok daha fazlad\u0131r. Tek bir Dockerfile ile build eden bir imaj bu ara\u00e7lar\u0131n hepsini \u00fcretime ta\u015f\u0131r: gereksiz yere b\u00fcy\u00fck, daha yava\u015f indirilen ve sald\u0131r\u0131 y\u00fczeyi geni\u015f bir imaj. <strong>Multi-stage build<\/strong> bu sorunu tek bir Dockerfile i\u00e7inde, birden fazla <code>FROM<\/code> kullanarak \u00e7\u00f6zer.<\/p>\n<h2>Fikir: derle bir yerde, \u00e7al\u0131\u015ft\u0131r ba\u015fka yerde<\/h2>\n<p>Her <code>FROM<\/code> yeni bir &#8220;a\u015fama&#8221; (stage) ba\u015flat\u0131r. Bir a\u015famada derlersiniz; son a\u015famada ise yaln\u0131zca derleme \u00e7\u0131kt\u0131s\u0131n\u0131 <code>COPY --from<\/code> ile al\u0131p temiz bir imaja koyars\u0131n\u0131z. \u00d6nceki a\u015famalar nihai imaja girmez.<\/p>\n<pre><code># A\u015fama 1 \u2014 derleme (b\u00fcy\u00fck ara\u00e7 seti burada)\nFROM temel-imaj AS build\nRUN head -c 30000000 \/dev\/zero &gt; \/buyuk-arac-seti.bin\nRUN echo \"derlenmis-uygulama\" &gt; \/app.bin\n\n# A\u015fama 2 \u2014 nihai imaj (yaln\u0131zca \u00e7\u0131kt\u0131)\nFROM temel-imaj\nCOPY --from=build \/app.bin \/app.bin\nCMD [\"\/bin\/cat\", \"\/app.bin\"]<\/code><\/pre>\n<p>Burada 30 MB&#8217;l\u0131k &#8220;ara\u00e7 seti&#8221; yaln\u0131zca <code>build<\/code> a\u015famas\u0131nda vard\u0131r. Ayn\u0131 i\u015fi tek a\u015famada yapan s\u00fcr\u00fcmle kar\u015f\u0131la\u015ft\u0131ral\u0131m:<\/p>\n<pre><code>$ docker images --format '{{.Repository}}:{{.Tag}} {{.Size}}' | sort\nms:multi   21.1MB\nms:single  51.2MB<\/code><\/pre>\n<p>Tek a\u015famal\u0131 imaj <strong>51,2 MB<\/strong>, multi-stage imaj <strong>21,1 MB<\/strong> \u2014 fark, ara\u00e7 setinin nihai imaja girmemesinden gelir. Ger\u00e7ek projelerde bu fark \u00e7ok daha dramatiktir (derleyici ve ba\u011f\u0131ml\u0131l\u0131klar y\u00fczlerce MB olabilir).<\/p>\n<h2>A\u015famalara ad verin<\/h2>\n<p><code>AS ad<\/code> ile a\u015famalara isim verebilirsiniz; <code>COPY --from=build<\/code> gibi referanslar s\u0131raya (<code>--from=0<\/code>) ba\u011f\u0131ml\u0131 olmaz ve Dockerfile&#8217;a yeni a\u015fama ekledi\u011finizde bozulmaz. Ba\u015fka bir imajdan da do\u011frudan dosya kopyalayabilirsiniz:<\/p>\n<pre><code>COPY --from=nginx:latest \/etc\/nginx\/nginx.conf \/nginx.conf<\/code><\/pre>\n<h2>Belirli bir a\u015famada durmak: <code>--target<\/code><\/h2>\n<p>Hata ay\u0131klarken ya da sadece test a\u015famas\u0131n\u0131 \u00e7al\u0131\u015ft\u0131rmak istedi\u011finizde <code>--target<\/code> ile build&#8217;i o a\u015famada durdurabilirsiniz:<\/p>\n<pre><code>docker build --target build -t ornek:build .<\/code><\/pre>\n<p>Dikkat: <code>--target build<\/code> ile \u00fcretilen imaj, nihai imaj de\u011fil <em>build a\u015famas\u0131n\u0131n tamam\u0131d\u0131r<\/em>; bizim denememizde 51,2 MB \u00e7\u0131kt\u0131. Bu imaj\u0131 \u00fcretime g\u00f6ndermemeniz gerekti\u011fini unutmay\u0131n.<\/p>\n<h2>BuildKit gereksiz a\u015famalar\u0131 atlar<\/h2>\n<p>Dockerfile&#8217;a \u015f\u00f6yle bir <code>test<\/code> a\u015famas\u0131 ekleyelim, ama nihai a\u015fama bundan hi\u00e7bir \u015fey kopyalamas\u0131n:<\/p>\n<pre><code>FROM temel-imaj AS test\nCOPY --from=build \/app.bin \/app.bin\nRUN echo \"testler gecti\"<\/code><\/pre>\n<p>BuildKit (Docker&#8217;\u0131n modern build motoru ve varsay\u0131lan builder) yaln\u0131zca hedef a\u015faman\u0131n ba\u011f\u0131ml\u0131 oldu\u011fu a\u015famalar\u0131 \u00e7al\u0131\u015ft\u0131r\u0131r. <code>--progress=plain<\/code> \u00e7\u0131kt\u0131s\u0131n\u0131 inceledi\u011fimizde <code>test<\/code> a\u015famas\u0131n\u0131n hi\u00e7 \u00e7al\u0131\u015fmad\u0131\u011f\u0131n\u0131 do\u011frulad\u0131k. Bu \u00f6zelli\u011fi &#8220;iste\u011fe ba\u011fl\u0131&#8221; a\u015famalar i\u00e7in kullanabilirsiniz: test a\u015famas\u0131n\u0131 yaln\u0131zca CI&#8217;da <code>--target test<\/code> ile \u00e7al\u0131\u015ft\u0131r\u0131n, normal build&#8217;de hi\u00e7 \u00e7al\u0131\u015fmas\u0131n.<\/p>\n<h2>Ger\u00e7ek d\u00fcnya kal\u0131b\u0131<\/h2>\n<p>Yayg\u0131n bir kal\u0131p, derleme i\u00e7in tam bir SDK imaj\u0131, \u00e7al\u0131\u015ft\u0131rma i\u00e7in minimal bir imaj kullanmakt\u0131r. \u00d6rne\u011fin bir Go uygulamas\u0131nda:<\/p>\n<pre><code>FROM golang:1.26 AS build\nWORKDIR \/src\nCOPY . .\nRUN CGO_ENABLED=0 go build -o \/bin\/uygulama .\n\nFROM scratch\nCOPY --from=build \/bin\/uygulama \/bin\/uygulama\nENTRYPOINT [\"\/bin\/uygulama\"]<\/code><\/pre>\n<p>Statik derlenmi\u015f bir ikili <code>scratch<\/code> (bo\u015f) imajda \u00e7al\u0131\u015fabilir; sonu\u00e7 birka\u00e7 MB&#8217;l\u0131k, i\u00e7inde kabuk bile bulunmayan bir imajd\u0131r. Node.js, Python ya da Java gibi \u00e7al\u0131\u015fma zaman\u0131 gerektiren dillerde son a\u015fama genellikle <code>-slim<\/code>, <code>alpine<\/code> ya da distroless bir imaj olur (bkz. <a href=\"https:\/\/konteynerium.com\/index.php\/2026\/07\/03\/container-image-guvenligi-zafiyet-taramasi-en-iyi-uygulamalar\/\">Container Image G\u00fcvenli\u011fi<\/a>).<\/p>\n<div class=\"callout\">\n  <span class=\"glyph\">\u2713<\/span><\/p>\n<p>G\u00fcvenlik kazanc\u0131 da vard\u0131r: derleyici, paket y\u00f6neticisi ve test ara\u00e7lar\u0131 nihai imajda olmad\u0131\u011f\u0131 i\u00e7in, bir sald\u0131rgan container&#8217;a s\u0131zsa bile elinde kullanabilece\u011fi ara\u00e7 \u00e7ok azd\u0131r.<\/p>\n<\/div>\n<h2>H\u0131zl\u0131 kontrol listesi<\/h2>\n<ul>\n<li>Derleme ara\u00e7lar\u0131 nihai imaj\u0131n d\u0131\u015f\u0131nda m\u0131?<\/li>\n<li>A\u015famalara <code>AS ad<\/code> verdiniz mi?<\/li>\n<li>Ba\u011f\u0131ml\u0131l\u0131k kurulumu (<code>COPY package.json<\/code> + <code>RUN npm ci<\/code>) kaynak koddan <em>\u00f6nce<\/em> geliyor mu? (bkz. <a href=\"https:\/\/konteynerium.com\/index.php\/2026\/10\/03\/buildkit-build-cache-hizli-docker-build\/\">Build Cache<\/a>)<\/li>\n<li>Test gibi iste\u011fe ba\u011fl\u0131 i\u015fler ayr\u0131 bir a\u015famada m\u0131?<\/li>\n<\/ul>\n<p>\u0130lk ad\u0131mlar i\u00e7in <a href=\"https:\/\/konteynerium.com\/index.php\/2026\/05\/01\/dockerfile-yazmaya-giris\/\">Dockerfile Yazmaya Giri\u015f<\/a> yaz\u0131s\u0131na, t\u00fcm bunlar\u0131n birle\u015fti\u011fi uygulamal\u0131 bir \u00f6rnek i\u00e7in <a href=\"https:\/\/konteynerium.com\/index.php\/2026\/09\/04\/uctan-uca-ornek-proje-nodejs-api-production\/\">U\u00e7tan Uca \u00d6rnek Proje<\/a> yaz\u0131s\u0131na bakabilirsiniz.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Multi-stage build ile derleme ara\u00e7lar\u0131n\u0131 nihai imaj\u0131n d\u0131\u015f\u0131nda b\u0131rakarak imaj\u0131 51 MB&#8217;tan 21 MB&#8217;a nas\u0131l d\u00fc\u015f\u00fcrece\u011finizi, &#8211;target kullan\u0131m\u0131n\u0131 ve BuildKit&#8217;in gereksiz a\u015famalar\u0131 nas\u0131l atlad\u0131\u011f\u0131n\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":[3],"tags":[],"seviye":[8],"class_list":["post-614","post","type-post","status-publish","format-standard","hentry","category-docker-derinlemesine","seviye-orta"],"_links":{"self":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts\/614","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=614"}],"version-history":[{"count":0,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts\/614\/revisions"}],"wp:attachment":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/media?parent=614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/categories?post=614"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/tags?post=614"},{"taxonomy":"seviye","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/seviye?post=614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}