Docker v17.05 introduced multi-stage builds giving us more ways to package and secure our applications. This post will show you how to use the power of the multi-stage builds for your projects. Check out the below Dockerfile and try to guess what we are trying to achieve here. We will go through each of the steps in detail right after that.
# Step 1 FROM node:10-alpine AS base WORKDIR /app COPY package.json . # Step 2 FROM base AS dependencies RUN npm install --only=production RUN cp -R node_modules prod_node_modules RUN npm install # Step 3 FROM dependencies AS build COPY . . RUN npm run build # Step 4 FROM base AS final COPY --from=dependencies /app/prod_node_modules ./node_modules COPY --from=build /app/dist ./dist COPY --from=build /app/entrypoint entrypoint RUN chmod +x entrypoint EXPOSE 3000 ENTRYPOINT [ "sh", "entrypoint" ]
Now let us go through the multiple stages we have used to create our final image -
node:10-alpineimage and naming it as
baseso that we can use it later in our build stage. This build stage will have only basic instructions. Here we have mentioned where our working directory will be an added our node projects
package.jsonfile to the working directory.
- We now take the
baseimage and start building our
dependenciesimage. Firstly we install only production dependencies then copy the node_modules directory to prod_node_modules directory. Then we install our dev dependencies on top of it. Step 4 will unravel why we did this.
- We then take the
dependenciesimage and start building our
Now we pick only required directories for our final image. Which includes -
- copying production node_modules from our
- copying our compiled/built code form
- copying our entrypoint script from
buildimage and giving it appropriate permissions.
- exposing the port for the application.
- adding the entrypoint. In this case, it is
The benefits of using multi-stage builds are -
- only the necessary files are kept in the final image. In this case, source files are not copied when we prepare the final image. This reduces the size of image.
- small image sizes reduce the deployment time.
- keeping the files and dependencies to the minimum improves security.
Hope you learned something new today!
Use multi-stage builds - https://docs.docker.com/develop/develop-images/multistage-build