This is a followup interactive tutorial from this blogpost to reduce docker nodejs images by 50% using Zeit pkg and docker multi-stage builds.

The traditional way

Before jumping into the magic trick, we’ll build a nodejs docker image as we would do traditionally to show the space that we’re saving by using this new approach.

Let’s create a simple node application:

echo 'console.log("Hello, pkg")' | tee index.js

We’ll now package it using a very basic dockerfile

echo 'FROM node:boron-slim
COPY . /app
CMD ["node", "/app/index.js"] ' | tee Dockerfile

Finally, we’ll build our image and check it’s size:

docker build -t myapp .
docker image ls | grep myapp

You can see that our myapp is 200+MB

Using PKG and multi-stage builds

Let’s create now a new Dockerfile that bundles our app with pkg and uses multi-stage builds to package it in a smaller docker image

echo 'FROM node:boron
RUN npm install -g pkg pkg-fetch

ENV NODE node6

RUN /usr/local/bin/pkg-fetch ${NODE} ${PLATFORM} ${ARCH}

COPY . /app
RUN /usr/local/bin/pkg --targets ${NODE}-${PLATFORM}-${ARCH} index.js

FROM debian:jessie-slim
COPY --from=0  /app/index /
CMD ["/index"]' | tee Dockerfile-pkg

We’ll build our app the same way as before but using our new Dockerfile:

docker build -t myapp_pkg -f Dockerfile-pkg .
docker image ls | grep myapp_pkg

As you can see, our new docker image is around 100MB and it works as expected:

docker run myapp_pkg