This post is over 1 year old and may be out of date or no longer relevant. If you find any problems with this post you can let me know by submitting an issue or editing this page.

Slimming Down node_modules in Docker Images

Everyone knows the meme about the size of the node_modules folder so I'll try to make this one quick. You can (in some cases) drastically reduce the size of a resulting docker image by avoiding the inclusion of non-production node modules.

Create a builder image

This is an easy one, and probably something you're already used to doing. Create a Dockerfile as you would normally but this time we'll add an as keyword. This essentially creates a name for the current image in the FROM line.

FROM node:8-alpine as builder

COPY src/ ./src
COPY package* ./
COPY tsconfig.json ./

RUN npm install
RUN npm run build

Install your production dependencies

We're also going to use the same as keyword in this image to tell the final image where to get the production dependencies from.

FROM node:10-alpine as dependencies

# Copy over the original package.json, we need this to npm install!
COPY --from=builder /app/package* ./

RUN npm install --production

Compose your final image

Now we can reference the previous images using the --from argument * gasps *. This means we can compose a final image from all the previous stages without the node_modules bloat.

FROM node:10-alpine

# Copy over our built application code
COPY --from=builder /app/dist ./dist

# Copy over the original package.json so we know how to start it
COPY --from=builder /app/package.json .

# Copy over our hopefully much lighter node_modules folder
COPY --from=dependencies /app/node_modules ./node_modules

CMD ["npm", "run", "start"]

Putting all three snippets together in a single Dockerfile should achieve a much thinner image now that we're not including all our development dependencies as well.

For more about multi-stage builds, see the official Docker documentation.

🎧 Nothing playingShow history