Docker - multi-stage builds

Let’s say that you want to build an image to serve frontend application. Just static files.

That’s what we need to do:

  1. Build an application.
  2. Run Nginx to serve static files.

To make the first point, we would like to use NodeJS image and Nginx image for the second one.

Of course, we can use Ubuntu image, install NodeJS and Nginx, build the application and serve the files but it’s not the best idea, is it?

We can use multi-stage builds.

You can read more about it in the documentation. I just want to share a small example which should give enough information to show what it is and how to use it.

FROM node:9.7.1-alpine as builder


RUN apk add --update \

RUN mkdir -p /usr/src/app
ADD website /usr/src/app

WORKDIR /usr/src/app

RUN yarn install && \
  yarn build

FROM nginx:1.12.2-alpine

COPY --from=builder /usr/src/app/dist/public /usr/share/nginx/html

COPY nginx/nginx.conf /etc/nginx/nginx.conf

What happens here? As you can see, we use two stages to build our image.

In the first stage, we use NodeJS image and call this stage as builder (as builder). The rest of the code should be easy and it’s not related to multi-stage builds. We allow to pass NODE_ENV as build argument, install git, add our website code and run yarn install && yarn build to build our application.

In the second stage, we use Nginx image to serve our application. The most important is the COPY instruction. As you can see, using --from=builder we can copy files from the first stage to the second one.

Using this way, we use NodeJS image to build our application and Nginx image to serve the static files. The final image is based only on Nginx image, the first stage is used just to build the application, nothing more.