Bird
Raised Fist0
Nginxdevops~5 mins

Multi-stage builds for static sites in Nginx - Commands & Configuration

Choose your learning style10 modes available
Introduction
Building static websites often requires preparing files before serving them. Multi-stage builds let you create a small final image by separating the build steps from the serving steps, saving space and improving security.
When you want to compile or build your static site files before serving them with nginx.
When you want to keep your final Docker image small by removing build tools.
When you want to speed up deployment by caching build steps separately.
When you want to separate concerns: build environment vs production environment.
When you want to avoid shipping unnecessary files or dependencies in your final image.
Config File - Dockerfile
Dockerfile
FROM node:18-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:1.25-alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

The first stage uses a lightweight Node.js image to install dependencies and build the static site files into the dist folder.

The second stage uses the official nginx image to serve the built files. It copies only the dist folder from the build stage, keeping the final image small and clean.

The EXPOSE 80 tells Docker the container listens on port 80, and the CMD runs nginx in the foreground.

Commands
Builds the Docker image using the multi-stage Dockerfile. This runs the build stage first, then creates the final nginx image with the built static files.
Terminal
docker build -t my-static-site .
Expected OutputExpected
Sending build context to Docker daemon 10.24MB Step 1/8 : FROM node:18-alpine AS build ---> 3a1f1a2b4c5d Step 2/8 : WORKDIR /app ---> Using cache ---> 7f8e9d0a1b2c Step 3/8 : COPY package.json package-lock.json ./ ---> Using cache ---> 1a2b3c4d5e6f Step 4/8 : RUN npm ci ---> Running in abcdef123456 added 50 packages in 2s Removing intermediate container abcdef123456 ---> 9f8e7d6c5b4a Step 5/8 : COPY . . ---> 123456abcdef Step 6/8 : RUN npm run build ---> Running in fedcba654321 > my-app@1.0.0 build /app > vite build vite v4.3.9 building for production... ✓ 10 modules transformed. dist/index.html dist/assets/index.123abc.js Removing intermediate container fedcba654321 ---> 0a1b2c3d4e5f Step 7/8 : FROM nginx:1.25-alpine ---> 7c8d9e0f1a2b Step 8/8 : COPY --from=build /app/dist /usr/share/nginx/html ---> Using cache ---> 4d3c2b1a0f9e Successfully built 4d3c2b1a0f9e Successfully tagged my-static-site:latest
Runs the built image in a container, mapping port 8080 on your computer to port 80 in the container where nginx serves the site.
Terminal
docker run -d -p 8080:80 --name static-site-container my-static-site
Expected OutputExpected
a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234567890
→
-d - Run container in detached mode (in background)
→
-p 8080:80 - Map host port 8080 to container port 80
→
--name static-site-container - Assign a name to the container for easy reference
Fetches the homepage from the running container to verify the static site is served correctly.
Terminal
curl http://localhost:8080
Expected OutputExpected
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>My Static Site</title> </head> <body> <h1>Welcome to My Static Site</h1> </body> </html>
Stops and removes the running container to clean up resources after testing.
Terminal
docker stop static-site-container && docker rm static-site-container
Expected OutputExpected
static-site-container static-site-container
Key Concept

If you remember nothing else from this pattern, remember: multi-stage builds let you separate building your static files from serving them, creating smaller and cleaner Docker images.

Common Mistakes
Copying source files directly into the nginx image without building first
Nginx cannot build or process static site files; it only serves files. Without building, the site may not work or be incomplete.
Use a build stage with Node.js or another tool to prepare the static files, then copy only the built files into the nginx image.
Not exposing the correct port or mapping ports incorrectly when running the container
If ports are not mapped, you cannot access the site from your computer's browser.
Use -p 8080:80 to map container port 80 to a host port like 8080.
Running nginx without the 'daemon off;' option in CMD
Nginx will start and immediately exit, causing the container to stop.
Use CMD ["nginx", "-g", "daemon off;"] to keep nginx running in the foreground.
Summary
Use a multi-stage Dockerfile to build static site files in one stage and serve them with nginx in the final stage.
Build the Docker image with 'docker build' to run the build and create a small final image.
Run the container with port mapping to access the site, then verify with curl or a browser.
Stop and remove the container after testing to keep your environment clean.

Practice

(1/5)
1. What is the main benefit of using multi-stage builds for static sites with nginx?
easy
A. It automatically updates static files without rebuilding the image.
B. It allows running multiple nginx servers in one container.
C. It reduces the final image size by separating build and serve stages.
D. It enables dynamic content generation inside the nginx container.

Solution

  1. Step 1: Understand multi-stage build purpose

    Multi-stage builds separate the build process from the final image, so only necessary files are included.
  2. Step 2: Identify benefits for static sites

    This separation reduces the final image size and improves security by excluding build tools from the runtime image.
  3. Final Answer:

    It reduces the final image size by separating build and serve stages. -> Option C
  4. Quick Check:

    Multi-stage builds = smaller images [OK]
Hint: Remember: build tools stay out of final image for smaller size [OK]
Common Mistakes:
  • Thinking multi-stage runs multiple nginx servers
  • Believing static files update automatically without rebuild
  • Confusing static site builds with dynamic content generation
2. Which Dockerfile snippet correctly copies static files from a builder stage to the nginx stage?
easy
A. COPY --to=builder /app/dist /usr/share/nginx/html
B. COPY /app/dist /usr/share/nginx/html --from=builder
C. COPY /usr/share/nginx/html /app/dist --from=builder
D. COPY --from=builder /app/dist /usr/share/nginx/html

Solution

  1. Step 1: Recall correct COPY syntax for multi-stage

    The syntax is COPY --from=stage source_path destination_path.
  2. Step 2: Match snippet to syntax

    COPY --from=builder /app/dist /usr/share/nginx/html uses COPY --from=builder /app/dist /usr/share/nginx/html which is correct.
  3. Final Answer:

    COPY --from=builder /app/dist /usr/share/nginx/html -> Option D
  4. Quick Check:

    COPY --from=stage source dest = correct [OK]
Hint: COPY uses --from=stage before source path [OK]
Common Mistakes:
  • Placing --from after paths
  • Using --to instead of --from
  • Reversing source and destination paths
3. Given this Dockerfile snippet, what will be the size impact on the final image?
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
medium
A. Final image will be small because only nginx and static files are included.
B. Final image will be empty because build files are not copied.
C. Final image will be large because node is included.
D. Final image will contain both node and nginx layers.

Solution

  1. Step 1: Analyze multi-stage build layers

    The builder stage uses node to build files, but the final stage uses nginx:alpine only.
  2. Step 2: Understand what is copied to final image

    Only the /app/dist folder from builder is copied into nginx image, so node and build tools are excluded.
  3. Final Answer:

    Final image will be small because only nginx and static files are included. -> Option A
  4. Quick Check:

    Multi-stage excludes build tools = smaller image [OK]
Hint: Final image excludes builder tools, so size stays small [OK]
Common Mistakes:
  • Assuming node stays in final image
  • Thinking build files are missing
  • Believing both node and nginx layers combine
4. You wrote this Dockerfile but the static files are missing in the nginx container:
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm run build

FROM nginx:alpine
COPY /app/dist /usr/share/nginx/html
What is the error?
medium
A. COPY command misses --from=builder to copy from the build stage.
B. npm run build did not generate files in /app/dist.
C. nginx:alpine image does not support static files.
D. WORKDIR is not set in the nginx stage.

Solution

  1. Step 1: Check COPY command in final stage

    The COPY command lacks --from=builder, so it copies from the current stage which is empty.
  2. Step 2: Understand multi-stage copy syntax

    To copy files from builder stage, COPY must use --from=builder to access that stage's files.
  3. Final Answer:

    COPY command misses --from=builder to copy from the build stage. -> Option A
  4. Quick Check:

    Missing --from=builder causes empty copy [OK]
Hint: Always use --from=builder to copy from build stage [OK]
Common Mistakes:
  • Forgetting --from=builder in COPY
  • Assuming build files auto-copy without --from
  • Blaming nginx image for missing files
5. You want to optimize your multi-stage Dockerfile for a static site by minimizing layers and image size. Which approach is best?
hard
A. Combine build and nginx in one stage to avoid copying files.
B. Use a builder stage to create static files, then copy only those files into a minimal nginx image.
C. Install node and build tools inside the nginx image to keep one image.
D. Copy the entire project folder into nginx image to ensure all files are present.

Solution

  1. Step 1: Understand multi-stage build best practices

    Best practice is to separate build tools from runtime to keep images small and secure.
  2. Step 2: Choose approach minimizing layers and size

    Using a builder stage to create static files, then copying only those files into a minimal nginx image achieves this.
  3. Final Answer:

    Use a builder stage to create static files, then copy only those files into a minimal nginx image. -> Option B
  4. Quick Check:

    Separate build and serve stages = optimized image [OK]
Hint: Build separately, copy only static files to nginx [OK]
Common Mistakes:
  • Combining build and serve increases image size
  • Installing build tools in nginx image adds unnecessary layers
  • Copying entire project wastes space and layers
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard