Skip to main content

Overview

Mizen includes Docker support for containerized deployment. While the project doesn’t currently include a complete Dockerfile in the repository, this guide shows you how to run Mizen with Docker.

Prerequisites

  • Docker installed and running
  • Docker Compose (optional, for multi-container setups)
  • Basic understanding of Docker concepts

Quick Start with Docker

The project includes npm scripts for common Docker operations:
npm run docker:build

Docker Build

The docker:build script builds a Docker image named parse-n-plate:
npm run docker:build
This is equivalent to running:
docker build -t parse-n-plate .

Docker Run

The docker:run script runs the container with environment variables:
npm run docker:run
This is equivalent to:
docker run -p 3000:3000 --env-file .env.local recipe-app

What This Does

  • -p 3000:3000 - Maps port 3000 from the container to port 3000 on your host
  • --env-file .env.local - Loads environment variables from .env.local
  • recipe-app - The name of the container to run

Creating a Dockerfile

If you need to create a Dockerfile for your project, here’s a recommended Next.js Dockerfile:
Dockerfile
# Stage 1: Install dependencies
FROM node:24.4.1-alpine AS deps
WORKDIR /app

# Copy package files
COPY package.json package-lock.json* ./

# Install dependencies
RUN npm ci

# Stage 2: Build the application
FROM node:24.4.1-alpine AS builder
WORKDIR /app

# Copy dependencies from deps stage
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Build the Next.js application
RUN npm run build

# Stage 3: Run the application
FROM node:24.4.1-alpine AS runner
WORKDIR /app

ENV NODE_ENV production

# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# Copy built application
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

# Set correct permissions
RUN chown -R nextjs:nodejs /app

USER nextjs

EXPOSE 3000

ENV PORT 3000
ENV HOSTNAME "0.0.0.0"

CMD ["node", "server.js"]

Docker Ignore

The project includes a .dockerignore file to exclude unnecessary files from the Docker build context:
.dockerignore
node_modules
.next
.git
.env.local
.env.development.local
.env.test.local
.env.production.local
*.env
Environment files are excluded from the Docker image for security. You must provide them at runtime using --env-file or environment variable flags.

Environment Variables in Docker

There are multiple ways to provide environment variables to Docker containers:

Method 1: Using --env-file

The recommended approach for local development:
docker run -p 3000:3000 --env-file .env.local mizen

Method 2: Individual Environment Variables

Pass variables directly:
docker run -p 3000:3000 \
  -e GROQ_API_KEY=your_key \
  -e NEXT_PUBLIC_SUPABASE_URL=your_url \
  -e NEXT_PUBLIC_SUPABASE_ANON_KEY=your_key \
  mizen

Method 3: Docker Compose

Create a docker-compose.yml file for easier management:
docker-compose.yml
version: '3.8'

services:
  mizen:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    env_file:
      - .env.local
    restart: unless-stopped
Then run:
docker-compose up

Multi-Stage Build Benefits

The recommended Dockerfile uses a multi-stage build approach:

Smaller Image

Only production dependencies and built files are included in the final image.

Better Security

Reduced attack surface by excluding development tools and source code.

Faster Builds

Docker caching optimizes rebuild times when dependencies don’t change.

Production Deployment

Building for Production

1

Build the production image

docker build -t mizen:latest .
2

Tag for your registry

docker tag mizen:latest your-registry.com/mizen:latest
3

Push to registry

docker push your-registry.com/mizen:latest
4

Deploy to your infrastructure

Pull and run the image on your production servers or container orchestration platform.

Health Checks

Add a health check to your Dockerfile:
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node -e "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"

Common Docker Commands

docker ps
docker logs <container-id>

# Follow logs in real-time
docker logs -f <container-id>
docker exec -it <container-id> sh
docker stop <container-id>
docker rm <container-id>
docker rmi <image-name>
# Remove unused containers, networks, and images
docker system prune

# Remove everything including volumes
docker system prune -a --volumes

Troubleshooting

Error: Bind for 0.0.0.0:3000 failed: port is already allocatedSolution: Either stop the process using port 3000 or map to a different port:
docker run -p 3001:3000 --env-file .env.local mizen
Issue: Application can’t access environment variablesSolution:
  • Verify .env.local exists and contains the required variables
  • Ensure --env-file flag points to the correct file
  • Check file permissions: chmod 644 .env.local
  • For Next.js public variables, ensure they’re prefixed with NEXT_PUBLIC_
Error: npm ERR! code ENOTFOUND or similar during buildSolution:
  • Check your internet connection
  • Verify package.json and package-lock.json are present
  • Try clearing Docker build cache: docker build --no-cache -t mizen .
Issue: Container starts but exits right awaySolution:
  • Check logs: docker logs <container-id>
  • Verify the CMD or ENTRYPOINT in your Dockerfile
  • Ensure required environment variables are set
  • Check for application errors in the logs

Docker Compose with Database

If you want to run Mizen with a local database for development:
docker-compose.yml
version: '3.8'

services:
  mizen:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    env_file:
      - .env.local
    depends_on:
      - postgres
    restart: unless-stopped

  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: mizen
      POSTGRES_USER: mizen_user
      POSTGRES_PASSWORD: secure_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    restart: unless-stopped

volumes:
  postgres_data:

Best Practices

Use Specific Versions

Always specify exact Node.js versions in your Dockerfile (e.g., node:24.4.1-alpine) for reproducible builds.

Optimize Layer Caching

Copy package.json before source code so dependency layers are cached when code changes.

Use Alpine Images

Alpine-based images are smaller and more secure than standard images.

Run as Non-Root

Always create and use a non-root user in production containers for security.

Next Steps

Environment Setup

Configure environment variables for Docker containers

Installation

Local development setup without Docker

Build docs developers (and LLMs) love