- Published on
Running This Next.js Blog Locally and With Docker
- Authors

- Name
- Mehdi Akiki
Reference
Running This Next.js Blog Locally and With Docker
If you're working on this blog (or forked it), here's everything you need to run it locally or test it in Docker. No fluff, just the commands that work.
Prerequisites
You'll need:
- Node.js 20+ (check with
node --version) - Yarn (this project uses Yarn, not npm)
- Docker (optional, only if you want to test containerization)
Local Development (Fast & Easy)
First Time Setup
# Clone the repo (if you haven't)
git clone <your-repo-url>
cd <repo-name>
# Install dependencies
yarn install
# Create your environment file
cp .env.example .env
# Edit .env with your API keys (Buttondown, Formspree, etc.)
Run Development Server
# Start dev server with hot reload
yarn dev
# Open http://localhost:3000
# Edit files and see changes instantly
Build for Production
# Build the static site
yarn build
# Test the production build locally
yarn serve
# Open http://localhost:3000
That's it. For most development, yarn dev is all you need.
Docker Deployment (Production-Like Testing)
Why Use Docker?
- Test your blog exactly as it'll run in production
- Ensure environment variables load correctly
- Share consistent environments across machines
- Deploy anywhere that supports Docker
The BuildKit Issue
Important: This project has a Docker networking quirk on some Linux systems. Always build with DOCKER_BUILDKIT=0:
# This will fail on some systems
docker build -t mehdi-blog .
# This works
DOCKER_BUILDKIT=0 docker build -t mehdi-blog .
Or set it permanently:
export DOCKER_BUILDKIT=0
# Add to ~/.bashrc or ~/.zshrc to make permanent
Build the Docker Image
# Build from Dockerfile
DOCKER_BUILDKIT=0 docker build -t mehdi-blog .
# Takes ~40 seconds
# Generates 722 static pages
# Final image is ~500MB (Alpine-based)
Run the Container
# Run detached (in background)
docker run -d \
--name mehdi-blog \
-p 3000:3000 \
--env-file .env \
mehdi-blog
# Container starts in ~250ms
# Blog available at http://localhost:3000
Check Container Status
# See running containers
docker ps
# View logs
docker logs mehdi-blog
# Follow logs in real-time
docker logs -f mehdi-blog
# Check resource usage
docker stats mehdi-blog
Stop and Remove Container
# Stop gracefully
docker stop mehdi-blog
# Remove container
docker rm mehdi-blog
# Or do both at once
docker stop mehdi-blog && docker rm mehdi-blog
# Force kill (if it won't stop)
docker rm -f mehdi-blog
Rebuild After Changes
# Stop old container
docker stop mehdi-blog && docker rm mehdi-blog
# Rebuild image
DOCKER_BUILDKIT=0 docker build -t mehdi-blog .
# Run new container
docker run -d --name mehdi-blog -p 3000:3000 --env-file .env mehdi-blog
One-liner version:
docker rm -f mehdi-blog && \
DOCKER_BUILDKIT=0 docker build -t mehdi-blog . && \
docker run -d --name mehdi-blog -p 3000:3000 --env-file .env mehdi-blog
Docker Compose (Recommended for Regular Use)
Easier than remembering all those flags.
Start Everything
# Build and start
DOCKER_BUILDKIT=0 docker-compose up -d --build
# View logs
docker-compose logs -f
# Just start (without rebuilding)
docker-compose up -d
Stop Everything
# Stop containers
docker-compose down
# Stop and remove volumes (clean slate)
docker-compose down -v
Restart After Changes
# Rebuild and restart
docker-compose down
DOCKER_BUILDKIT=0 docker-compose up -d --build
Useful Docker Commands
Clean Up
# Remove stopped containers
docker container prune
# Remove unused images
docker image prune
# Remove everything unused (careful!)
docker system prune -a
# See all images
docker images
# Delete specific image
docker rmi mehdi-blog
Inspect Container
# Get container details
docker inspect mehdi-blog
# Check environment variables
docker exec mehdi-blog env | grep BUTTONDOWN
# Open shell inside container
docker exec -it mehdi-blog sh
# Check if container is healthy
docker inspect mehdi-blog | grep Health
Push to Docker Hub (Optional)
# Tag for Docker Hub
docker tag mehdi-blog yourusername/mehdi-blog:latest
# Login
docker login
# Push
docker push yourusername/mehdi-blog:latest
# Pull on another machine
docker pull yourusername/mehdi-blog:latest
docker run -d -p 3000:3000 --env-file .env yourusername/mehdi-blog:latest
Environment Variables
The blog needs these environment variables (stored in .env):
Required:
BUTTONDOWN_API_KEY- Newsletter subscriptionsNEXT_PUBLIC_FORMSPREE_KEY- Contact form
Optional:
NEXT_UMAMI_ID- AnalyticsNEXT_PUBLIC_GISCUS_*- Comments
Never commit .env to git. It's in .gitignore for a reason.
Use .env.example as a template:
cp .env.example .env
# Edit with your real keys
Troubleshooting
Port Already in Use
# Find what's using port 3000
lsof -i :3000
# Kill it
kill -9 <PID>
# Or use a different port
docker run -d -p 3001:3000 --name mehdi-blog --env-file .env mehdi-blog
Build Fails
# Clear Next.js cache
rm -rf .next
# Clear node_modules
rm -rf node_modules
yarn install
# Rebuild
yarn build
Docker Container Won't Start
# Check logs for errors
docker logs mehdi-blog
# Verify .env file exists
ls -la .env
# Check if environment variables loaded
docker exec mehdi-blog env
Changes Not Showing
# For local dev (yarn dev picks up changes automatically)
# Just refresh the browser
# For Docker, you need to rebuild
docker stop mehdi-blog && docker rm mehdi-blog
DOCKER_BUILDKIT=0 docker build -t mehdi-blog .
docker run -d --name mehdi-blog -p 3000:3000 --env-file .env mehdi-blog
Quick Reference
Development:
yarn dev # Start dev server
yarn build # Build for production
yarn serve # Test production build
Docker (single container):
DOCKER_BUILDKIT=0 docker build -t mehdi-blog .
docker run -d --name mehdi-blog -p 3000:3000 --env-file .env mehdi-blog
docker logs -f mehdi-blog
docker stop mehdi-blog && docker rm mehdi-blog
Docker Compose:
DOCKER_BUILDKIT=0 docker-compose up -d --build
docker-compose logs -f
docker-compose down
Cleanup:
docker rm -f mehdi-blog
docker system prune
What's Next?
Once you're happy with local testing:
- Commit your changes:
git add . && git commit -m "Update blog" - Push to GitHub:
git push - Deploy to Vercel (easiest) or your own VPS with Docker
See DEPLOYMENT.md for full deployment options.
That's all you need. Keep this page bookmarked if you ever forget the Docker commands. We've all been there.