I am familiar with the single stage docker file, Although when I am writing with the single stage docker file, I never consider the image size, security and optimizing build process.
Using Docker with node.js has always on my mind, and today I want to share my journey of learning about multi-stage Docker. I successfully wrote and ran a Dockerfile, and I'm excited to discuss the process and insights I've gained along the way.
One day, while discussing random topics with another developer, our conversation unexpectedly turned into an exciting topic i.e. Docker, Node.js, Docker security and image size. During the discussion, I was introduced to the concept which I have to research and have to implement while I am working with Docker. After our discussion ended with smiles all around, Then I began my research and I found multi-stage Docker builds where can reduce image size, enhance security and also improved build efficiency, among other benefits.
What I Learned About Multi-Stage Dockerfiles?
A multi-stage Dockerfile allows you to create more efficient images by separating the build process from the final runtime environment. This approach helps in minimizing the size of the final image and improving security. Here’s a basic overview of how a multi-stage Dockerfile works:
Basic Structure of a Multi-Stage Dockerfile
Build Stage: Contains all the tools and dependencies needed to build your application. This stage includes compiling code, installing build tools, and generating artifacts.
Final Stage: Uses a clean base image and copies only the necessary files from the build stage to produce a smaller, more secure final image.
Example
I am sharing an example of a Dockerfile for a Node.js application
create a file name as a Dockerfile
Dockerfile
# Stage 1: Build
FROM node:20.11.0-alpine AS build
WORKDIR /usr/src/app
# Copy package.json and yarn.lock
COPY package.json yarn.lock ./
RUN yarn
# Copy the rest of the application code
COPY . .
# Build the application
# RUN yarn build # Uncomment if you have a build step [TypeScript]
# Stage 2: Production
FROM node:20.11.0-alpine
WORKDIR /usr/src/app
# Copy only the build artifacts and runtime dependencies
COPY --from=build /usr/src/app/ ./
# COPY --from=build /usr/src/app/dist ./dist # Use this line if you have built files [TypeScript]
# Expose the port and define the command to run the application
EXPOSE 3001
# CMD [ "node", "dist/app.js" ] # Use this line if you are working with TS
CMD ["node", "src/app.js"]
Adding a .dockerignore
file to your project provides several benefits, helping to streamline the Docker build process and improve efficiency.
Here’s a sample .dockerignore
file that excludes common unnecessary files:
# Node modules
node_modules
# Build output
dist
build
# Logs
*.log
# Environment files
.env
# Git files
.git
.gitignore
# Dockerfile and other Docker-related files
Dockerfile*
.dockerignore
To Execute the Dockerfile
$ docker build -t node-app .
$ docker run -p 3001:3001 -e PORT=3001 -e NODE_ENVIRONMENT=development node-app
Benefits of Multi-Stage Builds
- Smaller Image Size: Reduces the size of the final image by excluding build tools and intermediate files..
- Improved Security: Alpine is designed to be a secure and efficient base, which helps maintain a smaller attack surface.
- Better Performance: Faster build times due to effective caching of stages.
- Cleaner Dockerfile: Separates concerns and improves readability and maintainability.
Mitigation Strategies
- Simplify: Use multi-stage builds only when needed and avoid unnecessary complexity.
- Comment: Add comments to explain each stage and step.
- Optimize Caching: Use Docker’s caching to speed up builds.
- Monitor Resources: Track and optimize resource usage during builds.
- Test: Verify each stage individually before combining them.
Research
I am sharing the resources; I have found while learning about multi-stage Docker builds. You can also learn from below resources.
Building Multi-Stage
Start Docker Multi-Stage
Mastering Docker Multi-Stage
Thank you.
Remember to keep learning and exploring new things.
Top comments (0)