🧹
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
WORKDIR /app
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
WORKDIR /app
# Copy over the original package.json, we need this to npm install!
COPY /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
WORKDIR /app
# Copy over our built application code
COPY /app/dist ./dist
# Copy over the original package.json so we know how to start it
COPY /app/package.json .
# Copy over our hopefully much lighter node_modules folder
COPY /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.