Incident timeline

    ← All articles

    Tips & tricks

    Make your Dockerfile smaller and your builds faster

    Four Dockerfile habits that shrink images and speed up deploys: multi-stage builds, layer order, a .dockerignore and a non-root user.

    · 1 min read

    In short

    • Use a multi-stage build so build tools never reach the final image
    • Copy package files first so dependency installs are cached
    • Add a .dockerignore and run as a non-root user

    Every service in a monorepo is built from its own Dockerfile, so small mistakes multiply by the number of services. Four habits fix most of it.

    1. Multi-stage builds

    Build in one stage, ship from another. The final image keeps only what runs.

    FROM node:22-alpine AS build
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    COPY . .
    RUN npm run build
    
    FROM node:22-alpine
    WORKDIR /app
    COPY --from=build /app/dist ./dist
    CMD ["node", "dist/server.js"]

    2. Order layers by how often they change

    Docker caches each step. Copy the files that change rarely (package*.json) before the ones that change constantly (your source), so installs are reused.

    3. Add a .dockerignore

    Keep junk out of the build context:

    node_modules
    .git
    .env
    dist

    4. Run as a non-root user

    Most official images ship a low-privilege user. Switch to it before the final command:

    USER node

    Before and after

    Typical first attemptAfter these four
    Final image containsbuild tools, dev deps, git historyonly the runtime and built code
    Dependency installon every deploycached until package.json changes
    Secrets in layerspossibleexcluded by .dockerignore

    For a full example in context, see deploying a Next.js app and API from one repo.

    Frequently asked questions

    Why is my Docker image so large?

    Usually because build tools, dev dependencies and the whole source tree end up in the final image. A multi-stage build and a .dockerignore remove most of that.

    Do smaller images deploy faster?

    Generally yes. Less to build, push and pull means quicker deploys and less memory pressure on the platform.