<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Docker on WSLIN</title><link>https://wslin.dev/tags/docker/</link><description>Recent content in Docker on WSLIN</description><generator>Hugo</generator><language>zh-tw</language><lastBuildDate>Tue, 21 Apr 2026 13:48:45 +0800</lastBuildDate><atom:link href="https://wslin.dev/tags/docker/index.xml" rel="self" type="application/rss+xml"/><item><title>【Docker】Multi-Stage Build 減少Image大小</title><link>https://wslin.dev/blog/docker-multi-stage-build-image/</link><pubDate>Tue, 21 Apr 2026 13:48:45 +0800</pubDate><guid>https://wslin.dev/blog/docker-multi-stage-build-image/</guid><description>&lt;p&gt;為了可以在CI build Docker Image時節省Image的大小，學了一下Multi-Stage build，這篇文章就來記錄一下。&lt;/p&gt;&#10;&lt;h2 id="image-layer"&gt;&#10; Image Layer&#10; &lt;a class="heading-link" href="#image-layer"&gt;&#10; &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;&#10; &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;&#10; &lt;/a&gt;&#10;&lt;/h2&gt;&#10;&lt;p&gt;首先最重要的概念就是，Docker的每個Image都是由多個Layer組成的，當我們在Dockerfile裡&lt;strong&gt;每執行一個指令&lt;/strong&gt;(e.g.&lt;code&gt;FROM, RUN, COPY...&lt;/code&gt;)時，都會在原有的Layer之上再建立一個新的Layer，且該指令對檔案的任何操作或是Diff都只會記錄在這個Layer中(如果是改上一個Layer就有的檔案會複製一份再改，不影響上個Layer的完整性，Copy-on-Write)。&lt;/p&gt;&#10;&lt;p&gt;所以說當我們要build一個新的Image時，裡面可能就會包含很多不同的階段，像是安裝套件、編譯、打包可執行檔等等，每個步驟可能都會在對應的Layer裡產生很多最終執行檔不需要的東西，例如快取、編譯工具，導致整包Image很肥大。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; &lt;span style="color:#e6db74"&gt;node:18&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;WORKDIR&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/app&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 複製 package.json 並安裝所有依賴 (包含 devDependencies)&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; package*.json ./&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RUN&lt;/span&gt; npm install&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 複製所有原始碼並進行編譯&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; . .&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RUN&lt;/span&gt; npm run build&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 啟動伺服器 (通常是 npm start)&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CMD&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;npm&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;start&amp;#34;&lt;/span&gt;]&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 【結果】映像檔大小：可能高達 1GB+ (包含 node_modules 和原始碼)&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="multi-stage-build"&gt;&#10; Multi-Stage Build&#10; &lt;a class="heading-link" href="#multi-stage-build"&gt;&#10; &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;&#10; &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;&#10; &lt;/a&gt;&#10;&lt;/h2&gt;&#10;&lt;p&gt;為了處理這個問題 Docker提供了多階段build的功能，我們只需要使用&lt;code&gt;FROM AS&lt;/code&gt;就可以把每個不同階段拆開來，只傳遞該階段重要的結果(Artifact)，其他用不到的東西都可以直接丟掉。&lt;/p&gt;</description></item></channel></rss>