DEV Community

Sohana Akbar
Sohana Akbar

Posted on

5 Dockerfile mistakes frontend devs make

Dockerizing frontend apps sounds simple — until node_modules disappears or your image is 1.2GB. Here are the most common mistakes I've seen (and made myself).

  1. Copying everything, then installing dependencies ❌ Wrong:

dockerfile
COPY . .
RUN npm install
RUN npm run build
Every code change invalidates the cache, forcing npm install to re-run. Slow.

✅ Right:

dockerfile
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
Docker caches the RUN npm install layer unless package.json changes. Much faster rebuilds.

  1. Using node:latest as the base image for production Your 900MB image includes compilers, npm, and Python — none of which your nginx server needs.

✅ Right: Multi-stage builds

dockerfile

Stage 1: build

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

Stage 2: serve

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
Final image: ~25MB instead of 900MB.

  1. Running as root in the container Your container runs as root by default. If someone sneaks into your container, they own the host's kernel namespaces.

✅ Right:

dockerfile
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
USER nextjs
For nginx images, they already have a nginx user — use it.

  1. Ignoring npm ci in favor of npm install npm install can update lock files and install different versions than your package-lock.json defines.

✅ Right:

dockerfile
COPY package*.json package-lock.json ./
RUN npm ci
npm ci:

Fails if lock file is out of sync

Installs exactly what's in the lock file

Is faster for CI/CD

  1. Leaving node_modules in the final stage You don't need dependencies in production if you're serving static files. But sometimes people do:

dockerfile
FROM node:20-alpine
COPY . .
RUN npm ci && npm run build
CMD ["npm", "run", "preview"] # still has dev dependencies!
✅ Right: Build once, discard everything except the output (see multi-stage example above). Only the dist or .next folder goes to production.

Quick checklist before you ship
Multi-stage build with static server

COPY package.json before RUN npm ci

Non-root user

npm ci not npm install

No dev dependencies in final image

Your frontend image doesn't need Node.js at runtime. Treat your Dockerfile like you treat your bundle — ship only what's necessary.

What mistake would you add? Drop it in the comments.

Top comments (0)