Using multi-stage builds in Docker helps reduce the size of the final image, optimize the build process, and maintain the maintainability of the Dockerfile. The core concept of multi-stage builds is to define multiple build stages within a single Dockerfile, with only the image generated from the last stage being used as the final product. This approach allows you to use a larger base image in the earlier stages for building and compiling the application, while the later stages can utilize a more minimal image to run the application.
Below, I'll demonstrate how to create multi-stage builds in Docker with a specific example. Suppose we need to build a simple Node.js application:
First Stage: Build Stage
In this stage, we use a larger base image containing Node.js and npm to install dependencies and build our application. This stage excludes unnecessary tools for the application runtime, such as compilers.
Dockerfile# Use a larger Node base image to build the application FROM node:14 AS builder WORKDIR /app COPY package.json package-lock.json ./\nRUN npm install\nCOPY . .\nRUN npm run build
Second Stage: Runtime Stage
In this stage, we use a smaller base image to run the application. This image only requires the minimal environment to execute the Node.js application.
Dockerfile# Use a smaller base image to run the application FROM node:14-slim WORKDIR /app COPY --from=builder /app/build /app\nEXPOSE 3000\nCMD ["node", "app.js"]
In the above Dockerfile, we define two stages: builder and the runtime stage. In the builder stage, we use the node:14 image to install dependencies and build the application. Then, in the runtime stage, we use the node:14-slim image and copy the built application from the builder stage to the runtime environment. As a result, the final image only contains the necessary files to run the Node.js application, significantly reducing the image size.
This method not only reduces the image size but also helps mitigate potential security risks, as the runtime image does not include unnecessary tools and dependencies used for building the application.