Docker multi-stage build is a feature that allows you to use multiple FROM
statements in your Dockerfile. Each FROM
statement defines a separate build stage, and you can selectively copy artifacts from one stage to another. This feature is useful for optimizing Docker images, reducing their size, and improving build performance.
Here's how Docker multi-stage build works and why it's important:
Optimizing Image Size: Multi-stage builds allow you to separate the build environment from the runtime environment. This means you can install build tools and dependencies in one stage and then copy only the necessary artifacts (e.g., compiled binaries, static files) to the final stage. As a result, your final Docker image is smaller because it only contains the runtime dependencies and artifacts needed to run the application.
Improving Build Performance: By breaking down the build process into multiple stages, Docker can reuse cached layers from previous stages, reducing the time it takes to rebuild the image. This is especially beneficial when working with large applications or complex build processes, as it helps speed up development cycles.
Simplifying Dockerfiles: Multi-stage builds help simplify Dockerfiles by separating different parts of the build process into distinct stages. This makes Dockerfiles easier to read, understand, and maintain, as each stage focuses on a specific aspect of the build process.
Enhancing Security: With multi-stage builds, you can minimize the attack surface of your Docker images by excluding build-time dependencies and tools from the final image. This reduces the risk of security vulnerabilities and helps improve the overall security posture of your applications.
Steps
step 0: Make sure that you have installed the docker and node js
docker --version
node --version
step 1: Now create the project
npm init
npm install express
touch index.js
Then inside index.js
// Import required modules
const express = require('express');
// Create an Express application
const app = express();
// Define a route
app.get('/', (req, res) => {
res.send('Hello, World!');
});
// Start the server
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
step2: Create the Dockerfile in which
# Use Node.js version 20 as the base image
FROM node:20
# Set the working directory inside the container
WORKDIR /
# Copy package.json and package-lock.json to the working directory
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code to the working directory
COPY . .
# Expose port 3000 to the outside world
EXPOSE 3000
# Command to run the application
CMD ["node", "index.js"]
step3: Then build the image by following image
sudo docker build -t express-app .
sudo docker images
see the size of the docker images
step4: Now change the Dockerfile into the multi-stage build
# Stage 1: Build stage
FROM node:14 AS build
# Set the working directory inside the container
WORKDIR /app
# Copy package.json and package-lock.json to the working directory
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code to the working directory
COPY . .
# Stage 2: Production image
FROM node:14-alpine
# Set the working directory inside the container
WORKDIR /app
# Copy built files and dependencies from the previous stage
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app .
# Expose port 3000 to the outside world
EXPOSE 3000
# Command to run the application
CMD ["node", "index.js"]
Finally, we the reduced image size
In this way, we can reduce the size of the docker image by docker multi-stage build
Thanks for reading