0
0
Dockerdevops~5 mins

Copying from build stage to final stage in Docker - Commands & Configuration

Choose your learning style9 modes available
Introduction
When building Docker images, you often want to keep the final image small by copying only the necessary files from a larger build environment. This technique uses multiple stages in a Dockerfile to copy files from a build stage to the final stage, reducing image size and improving efficiency.
When you compile code in one stage but only need the compiled output in the final image.
When you want to install build tools temporarily and exclude them from the final image.
When you want to separate dependencies needed for building from those needed for running.
When you want to reduce the size of your Docker image for faster downloads and deployments.
When you want to keep your final image clean and secure by excluding unnecessary files.
Config File - Dockerfile
Dockerfile
FROM node:18 AS build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:1.23 AS final-stage
COPY --from=build-stage /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

The FROM node:18 AS build-stage starts the build stage where the app is built.

The WORKDIR sets the working directory inside the container.

COPY and RUN commands install dependencies and build the app.

The second stage FROM nginx:1.23 AS final-stage uses a lightweight web server image.

COPY --from=build-stage copies only the built files from the build stage to the final image.

This keeps the final image small and clean.

Commands
Builds the Docker image using the Dockerfile in the current directory. It runs both stages and creates the final image with the built app copied from the build stage.
Terminal
docker build -t my-app:latest .
Expected OutputExpected
[+] Building 12.3s (10/10) FINISHED => [build-stage 1/7] FROM docker.io/library/node:18 0.0s => CACHED [build-stage 2/7] WORKDIR /app 0.0s => [build-stage 3/7] COPY package*.json ./ 0.1s => [build-stage 4/7] RUN npm install 8.5s => [build-stage 5/7] COPY . . 0.1s => [build-stage 6/7] RUN npm run build 3.2s => [final-stage 7/10] FROM docker.io/library/nginx:1.23 0.0s => [final-stage 8/10] COPY --from=build-stage /app/build /usr/share/nginx/html 0.1s => [final-stage 9/10] EXPOSE 80 0.0s => [final-stage 10/10] CMD ["nginx", "-g", "daemon off;"] 0.0s => exporting to image 0.1s => => exporting layers 0.1s => => writing image sha256:abcdef1234567890 0.0s => => naming to docker.io/library/my-app:latest
Runs the built Docker image in detached mode, mapping port 8080 on the host to port 80 in the container so you can access the app in a browser.
Terminal
docker run -d -p 8080:80 my-app:latest
Expected OutputExpected
a1b2c3d4e5f67890123456789abcdef0123456789abcdef0123456789abcdef0
-d - Run container in detached mode (in background)
-p 8080:80 - Map host port 8080 to container port 80
Fetches the homepage from the running container to verify the app is served correctly from the final image.
Terminal
curl http://localhost:8080
Expected OutputExpected
<!DOCTYPE html> <html> <head> <title>My App</title> </head> <body> <h1>Welcome to My App</h1> </body> </html>
Lists the Docker images named 'my-app' to check the image size and confirm the build was successful.
Terminal
docker images my-app
Expected OutputExpected
REPOSITORY TAG IMAGE ID CREATED SIZE my-app latest abcdef123456 10 seconds ago 45MB
Key Concept

If you remember nothing else from this pattern, remember: multi-stage builds let you copy only the needed files from a build stage to keep your final Docker image small and efficient.

Common Mistakes
Not using the --from flag in COPY to specify the build stage.
Docker will look for files in the current stage, causing a build error because the files don't exist there.
Use COPY --from=build-stage /path/in/build /path/in/final to copy files from the build stage.
Copying the entire build directory instead of just the output files.
This makes the final image unnecessarily large and may include sensitive or unnecessary files.
Copy only the build output folder or files needed to run the app.
Not naming the build stage with AS, so you can't reference it in COPY.
Without a stage name, you cannot use --from to copy files from that stage.
Name your build stage with AS build-stage (or any name) to reference it later.
Summary
Use multi-stage Dockerfiles to separate build and final stages.
Copy only the necessary build output from the build stage to the final stage using COPY --from.
This approach keeps the final image small and efficient for deployment.