Tuesday, February 10, 2026

AWS - Multi-Stage Docker Build

Multi stage sample docker file

# Build stage

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build

WORKDIR /app

COPY . .

RUN dotnet publish -c Release -o out

# Runtime stage

FROM mcr.microsoft.com/dotnet/aspnet:8.0

WORKDIR /app

COPY --from=build /app/out .

ENTRYPOINT ["dotnet", "MyApp.dll"]


This Dockerfile uses Multi-Stage Build:

  • Stage 1 → Build the app
  • Stage 2 → Run the app

The RUN command executes during image build time, not when the container starts.




Stage 1 – Build Stage

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
  • Pulls Microsoft .NET SDK image
  • SDK contains compiler, NuGet, build tools
  • Named this stage build


WORKDIR /app

  • Sets working directory inside container to /app
  • All next commands run from here


COPY . .

  • Copies your entire project folder from local machine → container /app
  • Includes .csproj, source code, etc.


RUN dotnet publish -c Release -o out

This is the key line 

RUN executes a command while building the image.

Think of it as:

“Open a temporary container, run this command, save the result as a new image layer.”

What happens internally

  1. Docker creates a temporary container from sdk:8.0
  2. Runs:
    • dotnet publish -c Release -o out
  3. .NET does:

    • Restore NuGet packages
    • Compile code
    • Optimize for Release
    • Output DLLs + dependencies into /app/out
  4. Docker commits the result as a new image layer
  5. Temporary container is deleted

So RUN is build-time execution, not runtime.

Result now inside image:

/app/out/MyApp.dll
/app/out/*.json
/app/out/*.deps.json


Stage 2 – Runtime Stage

FROM mcr.microsoft.com/dotnet/aspnet:8.0
  • Starts a fresh lightweight image
  • No SDK, only runtime
  • Much smaller


WORKDIR /app

Sets working directory again.


COPY --from=build /app/out .
  • Copies only compiled output from build stage
  • Not source code
  • Not SDK
  • Only /app/out/app

This is why image becomes small.


ENTRYPOINT ["dotnet", "MyApp.dll"]

This runs when container starts, not during build.

Difference:

InstructionWhen it runs
RUNDuring docker build
ENTRYPOINTDuring docker run

Lifecycle Summary
When you run:

docker build -t myapp .

Docker executes:

  1. Pull SDK image
  2. Copy code
  3. RUN dotnet publish → compile app
  4. Start new runtime image
  5. Copy compiled files
  6. Create final image


When you run:

docker run myapp

Only this runs:

dotnet MyApp.dll

No compiling happens here.


Simple Analogy

  • RUN = “Bake the cake in the kitchen”
  • ENTRYPOINT = “Serve the cake to the customer”

RUN prepares the app.
ENTRYPOINT executes the app.


Why This Is Efficient

Without multi-stage:

  • Image ~1–2 GB
  • Includes compiler

With multi-stage:

  • Image ~150–250 MB
  • Only runtime files
  • Faster deploys
  • More secure

So RUN = build-time command that produces artifacts saved into the image layer.

No comments:

Post a Comment

CI/CD - Safe DB Changes/Migrations

Safe DB Migrations means updating your database schema without breaking the running application and without downtime . In real systems (A...