Skip to content
All articles
DockerDevOps

Docker for Frontend Devs: Everything You Need

A practical guide to Docker for engineers who mostly write React — no unnecessary DevOps jargon.

25 April 20269 min read

Why Frontend Engineers Should Care About Docker

For the first three years of my career, Docker was something the backend team dealt with. I wrote React, the DevOps team containerized it, and I never thought about it. Then I joined CARS24 where there was no DevOps team, and suddenly I needed to understand containers to ship my code.

Here's the reality: in 2026, frontend deployment is containerized at most companies. Even if you're deploying to Vercel or Netlify, understanding Docker makes you more versatile and helps you debug deployment issues that would otherwise be opaque.

The Only Dockerfile You Need for Next.js

I've seen Next.js Dockerfiles that are 50 lines long with multiple stages, custom entrypoints, and environment variable gymnastics. For most projects, you need three stages: install dependencies, build the application, and run it.

The key optimizations: use a node:alpine base image to keep the image small, copy package.json and lockfile before the source code to leverage Docker's layer caching for dependencies, and use Next.js standalone output mode to create a minimal production bundle without node_modules.

With standalone output, our production image at CARS24 was 120MB compared to 800MB with the standard node_modules approach. The smaller image means faster deployments and lower container registry costs.

Docker Compose for Local Development

Docker Compose is where Docker becomes genuinely useful for frontend development. Instead of asking new engineers to install Node, Redis, PostgreSQL, and Elasticsearch locally, we hand them a docker-compose.yml that spins up the entire stack with a single command.

At Flipkart, our docker-compose file defines four services: the Next.js dev server with hot reloading (volume-mounted to the host), a Redis instance, a mock API server, and a local S3-compatible storage using MinIO. New engineers go from git clone to a running application in under three minutes.

The trick for good developer experience is volume mounting your source code into the container so that file changes on your host machine trigger hot reloading inside the container. Without this, you'd need to rebuild the container after every code change, which defeats the purpose.

Multi-Stage Builds for Production

Multi-stage builds are the single most important Docker pattern for frontend applications. The idea is to use one stage for building (which needs dev dependencies, build tools, etc.) and a separate stage for running (which only needs the production output).

Your build stage installs all dependencies including devDependencies, runs your build command, and produces static assets or a server bundle. Your production stage copies only the build output into a clean image. This means your production image doesn't contain TypeScript, webpack, testing libraries, or anything else that's only needed during build.

At Mamaearth, switching to multi-stage builds reduced our production image size from 1.2GB to 180MB. The security surface area shrank proportionally because there were fewer packages to have vulnerabilities.

Common Pitfalls and How to Avoid Them

The number one mistake I see frontend engineers make with Docker is running the development server in production. If your Dockerfile ends with npm run dev, your container is running a development server with debugging enabled, source maps included, and no optimization. Use npm run start with a production build.

The second mistake is not using .dockerignore. Without it, Docker copies your node_modules, .git directory, and every other file into the build context. This slows down builds and can leak secrets into the image. Your .dockerignore should at minimum include node_modules, .git, .env, and any test or documentation directories.

The third mistake is hardcoding environment variables in the Dockerfile. Use ARG for build-time variables and ENV for runtime variables, and pass values through docker-compose or your deployment platform. Never commit secrets to a Dockerfile.

Found this useful? I write about engineering, performance, and career growth.