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.
- π₯ 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 --buildAccess at http://localhost:3000
Production (static export + Nginx)
docker compose up nextjs-export --buildAccess at http://localhost:8080
Note: 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