A comprehensive demonstration of containerizing a modern Next.js application using Docker for both development and production workflows. This project showcases industry best practices for front-end containerization, including standalone and static-export builds, development with live sync, and optimized production delivery.
Part of the official Docker Next.js sample guide.
For full reference, including all Docker files and setup details, switch to the development branch.
- π₯ Modern Next.js with App Router and TypeScript
- β‘ Standalone & static export β Node server or static files (Nginx / serve)
- π¨ Tailwind CSS for utility-first styling
- π³ Multi-stage Docker builds for optimized production images
- π§ Development & production Docker configurations with Compose Watch
- π§ͺ Testing with Vitest and Testing Library
- π¦ Docker Compose for easy orchestration
- βΈοΈ Kubernetes deployment configuration
- π Security-focused (non-root user, minimal base images)
- π ESLint for code quality
- π€ CI/CD with GitHub Actions (see
.github/workflows)
| Layer | Technologies |
|---|---|
| Framework | Next.js 16 (App Router), React 19, TypeScript |
| Styling | Tailwind CSS v4 |
| Testing | Vitest, React Testing Library |
| Container | Docker, Docker Compose |
| Orchestration | Kubernetes (optional) |
| Web Server | Nginx (static export), Node (standalone) |
- Docker (v20.10+)
- Docker Compose (v2.0+)
- Node.js (v24+) β for local development
- npm or yarn or pnpm β for local development
Clone the repository
git clone https://github.com/kristiyan-velkov/docker-nextjs-sample.git
cd docker-nextjs-sampleDevelopment with Docker Compose
docker compose up nextjs-dev --buildAccess the app at http://localhost:3000
Production (standalone)
docker compose up nextjs-prod-standalone --buildProduction (static export + Nginx)
docker compose up nextjs-export --buildNote: Only one service using port 8080 (nextjs-export, nextjs-prod-static-nginx, or nextjs-prod-static-serve) should run at a time.
Install dependencies
pnpm install
# or: npm install | yarn installStart development server
pnpm devRun tests
pnpm run test:runBuild for production
pnpm build# Build development image
docker build -f Dockerfile.dev -t nextjs-app-dev .
# Run development container
docker run -p 3000:3000 -v $(pwd):/app nextjs-app-dev
# Using Docker Compose (recommended, with watch)
docker compose watch nextjs-dev# Build production image
docker build -t nextjs-sample:latest .
# Run production container
docker run -p 3000:3000 nextjs-sample:latest# Build static export + Nginx
docker build -f Dockerfile.export -t nextjs-export .
docker run -p 8080:8080 nextjs-exportdocker compose --profile tools run --rm nextjs-test
docker compose --profile tools run --rm nextjs-lintDeploy the Next.js standalone app using the provided manifest:
# 1. Build the image (must match manifest)
docker build -t nextjs-sample:latest -f Dockerfile .
# 2. Apply the manifest (requires a running cluster, e.g. Docker Desktop K8s)
kubectl apply -f nextjs-sample-kubernetes.yamlThis creates:
- Deployment (
nextjs-sample) β 1 replica - Service (
nextjs-sample-service) β NodePort 30001
Access: http://localhost:30001 (Docker Desktop) or use minikube service nextjs-sample-service --url for minikube.
Cleanup
kubectl delete -f nextjs-sample-kubernetes.yamlSee README.Docker.md for detailed Kubernetes steps (Docker Desktop, minikube, kind).
βββ app/ # Next.js App Router
β βββ components/home/ # Home page components
β βββ data/ # Author, resources data
β βββ layout.tsx
β βββ page.tsx
β βββ globals.css
βββ public/ # Static assets
βββ Dockerfile # Next.js standalone (production)
βββ Dockerfile.dev # Next.js development
βββ Dockerfile.export # Next.js static export β Nginx
βββ Dockerfile.nginx # Next.js static export β Nginx (alt)
βββ Dockerfile.serve # Next.js static export β Node serve
βββ compose.yaml # Docker Compose configuration
βββ nginx.conf # Nginx config for static export
βββ nextjs-sample-kubernetes.yaml # Kubernetes deployment
βββ Taskfile.yml # Task automation
βββ README.Docker.md # Docker & Kubernetes guide
# Local testing
pnpm run test:run
# Testing in Docker
docker compose --profile tools run --rm nextjs-testThis setup follows security best practices:
- Non-root user (node / nginx) in production images
- Minimal base images (slim / Alpine where applicable)
- Lockfile-based installs for reproducible builds
- Multi-stage builds to keep final image small
| Variable | Description | Default |
|---|---|---|
PORT |
Application port | 3000 |
NODE_ENV |
Environment mode | development / production |
HOSTNAME |
Next.js server host | 0.0.0.0 |
NEXT_OUTPUT |
Next.js output mode | standalone (or export in export Dockerfiles) |
Create compose.override.yaml for local customizations:
services:
nextjs-dev:
ports:
- "3001:3000"
environment:
- CUSTOM_VAR=value| Command | Description |
|---|---|
pnpm dev |
Start Next.js dev server |
pnpm build |
Build for production |
pnpm start |
Start production server |
pnpm lint |
Run ESLint |
pnpm run test:run |
Run tests once |
pnpm test |
Run Vitest (watch) |
Contributions are welcome. Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License β see the LICENSE file for details.
Kristiyan Velkov
- LinkedIn: kristiyan-velkov
- Medium: @kristiyanvelkov
- Newsletter: Front-end World
- X: @krisvelkov
If you find this project helpful, consider supporting:
- GitHub Sponsors
- Buy Me a Coffee
- Revolut
