<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abhijeet Katore</title>
    <description>The latest articles on DEV Community by Abhijeet Katore (@abhijeet_katore).</description>
    <link>https://dev.to/abhijeet_katore</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3852759%2F6c382260-881b-451a-bee2-4c0045ae2170.png</url>
      <title>DEV Community: Abhijeet Katore</title>
      <link>https://dev.to/abhijeet_katore</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abhijeet_katore"/>
    <language>en</language>
    <item>
      <title>Docker multistage build short and simple explanation with command</title>
      <dc:creator>Abhijeet Katore</dc:creator>
      <pubDate>Tue, 31 Mar 2026 05:20:27 +0000</pubDate>
      <link>https://dev.to/abhijeet_katore/docker-multistage-build-short-and-simple-explanation-with-command-5811</link>
      <guid>https://dev.to/abhijeet_katore/docker-multistage-build-short-and-simple-explanation-with-command-5811</guid>
      <description>&lt;p&gt;A &lt;strong&gt;Docker multi-stage build&lt;/strong&gt; is a technique that uses multiple FROM instructions in a single Dockerfile to create smaller, more secure, and efficient container images. &lt;br&gt;
The core idea is "build fat, ship thin": &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stage 1 (The Build):&lt;/strong&gt; Use a heavy image with all the compilers, tools, and source code needed to build your app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 2 (The Runtime):&lt;/strong&gt; Use a lightweight image and only copy the final compiled application (the artifact) from the first stage. &lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Why use it?&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Smaller Size: Final images only contain what's needed to run, often reducing size by 90% or more (e.g., from 800MB to 20MB).&lt;/li&gt;
&lt;li&gt;Better Security: No compilers, source code, or extra packages are left in production, reducing the "attack surface".&lt;/li&gt;
&lt;li&gt;Simplicity: You manage everything in one file instead of separate build scripts. &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Simple Example (Go Application)
&lt;/h2&gt;

&lt;p&gt;This Dockerfile creates a tiny binary in the first stage and runs it in a minimal second stage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# STAGE 1: Build the app&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.21-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-o&lt;/span&gt; myapp main.go

&lt;span class="c"&gt;# STAGE 2: Create the final lean image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine:latest&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /root/&lt;/span&gt;
&lt;span class="c"&gt;# Copy ONLY the binary from the 'builder' stage&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/myapp .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["./myapp"]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Build Command
&lt;/h2&gt;

&lt;p&gt;You build a multi-stage image the same way as a regular one&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;docker build -t my-optimized-app .

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To build only a specific stage (useful for debugging), use the --target flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--target&lt;/span&gt; builder &lt;span class="nt"&gt;-t&lt;/span&gt; my-app-build-only &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Are these Dockerfiles are separately created? or coded in single Dockerfile?
&lt;/h2&gt;

&lt;p&gt;after building the docker file, will it be a single image? and is the from:alpine in stage 2 is taking the only Stage 1?&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Are they separate files?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt; All the stages are written in &lt;strong&gt;one single&lt;/strong&gt; &lt;code&gt;Dockerfile&lt;/code&gt;. You just use the &lt;code&gt;FROM&lt;/code&gt; instruction multiple times within that same file.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Will it be a single image?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Yes.&lt;/strong&gt; When the build finishes, Docker creates &lt;strong&gt;one single image&lt;/strong&gt; based on the very last FROM stage. All the intermediate layers and tools from the earlier "build" stages are discarded. You won't see them in your local image list.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Does FROM alpine in Stage 2 take Stage 1?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt; &lt;code&gt;FROM alpine&lt;/code&gt; tells Docker to start with a &lt;strong&gt;fresh, clean, tiny OS.&lt;/strong&gt; It does not automatically include anything from Stage 1.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Magic Link:&lt;/strong&gt; The only way Stage 2 gets anything from Stage 1 is when you explicitly ask for it using:&lt;/li&gt;
&lt;li&gt;COPY --from=builder /source/path /destination/path&lt;/li&gt;
&lt;li&gt;Think of Stage 1 as a &lt;strong&gt;temporary kitchen&lt;/strong&gt; where you cook the meal, and Stage 2 as the &lt;strong&gt;clean plate&lt;/strong&gt; where you only put the finished food. You throw away the messy kitchen (Stage 1) and only keep the plate (Stage 2).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  But why we need stage 2? if we have builder already? does the stage two creates the lean image based on Stage 1 and alpine:latest
&lt;/h2&gt;

&lt;p&gt;You need Stage 2 &lt;strong&gt;&lt;u&gt;because the Builder stage is usually huge.&lt;/u&gt;&lt;/strong&gt; It contains "heavy" tools like compilers, package managers, and your entire source code that you don't actually need to run the app.&lt;br&gt;
Think of it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stage 1 (The Factory):&lt;/strong&gt; Has the welding machines, blueprints, and scrap metal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 2 (The Showroom):&lt;/strong&gt; Only has the finished car.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Does Stage 2 create the image based on Stage 1?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt; Stage 2 creates the image based &lt;strong&gt;only on&lt;/strong&gt; &lt;code&gt;alpine:latest.&lt;/code&gt;&lt;br&gt;
It starts completely blank. It only becomes "based" on Stage 1 for a split second when you reach in and grab the finished executable file (the artifact) using the &lt;code&gt;COPY --from&lt;/code&gt; command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just use the Builder image?
&lt;/h2&gt;

&lt;p&gt;If you only used Stage 1 (the Builder), your final image would be massive (e.g., 800MB) because it keeps all the junk used during the build. By switching to Stage 2 (alpine), you ditch the junk and keep only the 5MB app, resulting in:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Faster Downloads:&lt;/code&gt; Pulling a 10MB image is faster than 800MB.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Better Security:&lt;/code&gt; Hackers can't use your own compilers or source code against you if they aren't there.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Less Storage:&lt;/code&gt; Your server stays clean.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Would you like to see a &lt;code&gt;size comparison&lt;/code&gt; between a single-stage and a multi-stage &lt;code&gt;Node.js&lt;/code&gt; or &lt;code&gt;Python&lt;/code&gt; image?&lt;/p&gt;

&lt;h2&gt;
  
  
  Then Why Not Just Use The Stage 2 Alone?
&lt;/h2&gt;

&lt;p&gt;Because &lt;strong&gt;Stage 2 (the lean image) doesn't have the tools to build your app.&lt;/strong&gt;&lt;br&gt;
If you use &lt;code&gt;alpine&lt;/code&gt; alone, it is a "bare bones" box. It doesn't have a Go compiler, a Java JDK, or a C++ builder. If you try to run a build command inside Stage 2, it will fail because the "tools" are missing.&lt;br&gt;
Here is the catch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stage 1&lt;/strong&gt; has the &lt;strong&gt;Tools&lt;/strong&gt; (heavy) but you don't want to ship them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 2&lt;/strong&gt; has the &lt;strong&gt;Small Size&lt;/strong&gt; (light) but it can't build anything.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The "Aha!" Moment
&lt;/h2&gt;

&lt;p&gt;You use &lt;code&gt;Stage 1&lt;/code&gt; to do the "dirty work" (compiling the code). Once the code is turned into a single executable file (an artifact), you &lt;code&gt;move&lt;/code&gt; that file into &lt;code&gt;Stage 2.&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;If you didn't have Stage 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You would have to compile the code on your personal laptop.&lt;/li&gt;
&lt;li&gt;Then, you'd have to hope your laptop's settings match the server's settings (which often causes "it works on my machine" bugs).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;By using both:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stage 1&lt;/strong&gt; ensures the build happens in a controlled, identical environment every time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 2&lt;/strong&gt; ensures the final product is as tiny as possible.&lt;/li&gt;
&lt;/ul&gt;




</description>
    </item>
  </channel>
</rss>
