Skip to main content
5Stack provides Docker configurations for both development and production deployments. This guide covers building and running the application in containerized environments.

Docker Images

5Stack includes two Dockerfile configurations:

Production

Dockerfile - Multi-stage optimized build

Development

Dockerfile.dev - Development with hot reload

Production Deployment

The production Dockerfile uses a multi-stage build to create an optimized image.

Build Process

The production build consists of three stages:
1

Dependencies Stage

Installs production dependencies in immutable mode:
FROM node:22-alpine AS deps
WORKDIR /opt/5stack
COPY package.json yarn.lock .yarnrc.yml ./
RUN corepack enable && corepack prepare
RUN yarn install --immutable
2

Builder Stage

Copies dependencies and builds the application:
FROM node:22-alpine AS builder
WORKDIR /opt/5stack
COPY --from=deps /opt/5stack/node_modules ./node_modules
COPY . .
RUN corepack enable && corepack prepare
RUN yarn build
The yarn build command runs nuxt build --standalone, creating a standalone output in .output/.
3

Runtime Stage

Creates the final minimal image with only the built application:
FROM node:22-alpine
WORKDIR /opt/5stack
COPY --from=builder /opt/5stack/.output .
ENV HOST=0.0.0.0
EXPOSE 3000
CMD [ "node", "server/index.mjs" ]

Building the Production Image

Build the production Docker image:
docker build -t 5stack:latest .
With custom tag:
docker build -t 5stack:v1.0.0 .

Running the Production Container

Basic run command:
docker run -p 3000:3000 5stack:latest
With environment variables:
docker run \
  -p 3000:3000 \
  -e NUXT_PUBLIC_WEB_DOMAIN=5stack.gg \
  -e NUXT_PUBLIC_API_DOMAIN=api.5stack.gg \
  -e NUXT_PUBLIC_WS_DOMAIN=ws.5stack.gg \
  -e NUXT_PUBLIC_RELAY_DOMAIN=relay.5stack.gg \
  -e NUXT_PUBLIC_DEMOS_DOMAIN=demos.5stack.gg \
  -e NUXT_PUBLIC_TYPESENSE_HOST=search.5stack.gg \
  5stack:latest
With detached mode and restart policy:
docker run -d \
  --name 5stack-web \
  --restart unless-stopped \
  -p 3000:3000 \
  --env-file .env \
  5stack:latest

Development Deployment

The development Dockerfile is optimized for local development with hot module replacement.

Development Image Structure

FROM node:22-alpine AS deps
WORKDIR /opt/5stack
COPY package.json yarn.lock .yarnrc.yml ./
RUN corepack enable && corepack prepare
RUN yarn install --immutable

FROM node:22-alpine
WORKDIR /opt/5stack
COPY package.json yarn.lock .yarnrc.yml ./
RUN corepack enable && corepack prepare
COPY --from=deps /opt/5stack/node_modules ./node_modules
COPY . .
ENV HOST=0.0.0.0
EXPOSE 3000
CMD [ "yarn", "dev" ]

Building the Development Image

docker build -f Dockerfile.dev -t 5stack:dev .

Running the Development Container

With volume mounting for hot reload:
docker run \
  -p 3000:3000 \
  -v $(pwd):/opt/5stack \
  -v /opt/5stack/node_modules \
  --env-file .env \
  5stack:dev
The volume mounts ensure:
  • Source code changes are reflected immediately
  • node_modules is preserved in the container

Docker Compose

For easier management, use Docker Compose:

Production Compose

docker-compose.yml
version: '3.8'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - NUXT_PUBLIC_WEB_DOMAIN=${NUXT_PUBLIC_WEB_DOMAIN}
      - NUXT_PUBLIC_API_DOMAIN=${NUXT_PUBLIC_API_DOMAIN}
      - NUXT_PUBLIC_WS_DOMAIN=${NUXT_PUBLIC_WS_DOMAIN}
      - NUXT_PUBLIC_RELAY_DOMAIN=${NUXT_PUBLIC_RELAY_DOMAIN}
      - NUXT_PUBLIC_DEMOS_DOMAIN=${NUXT_PUBLIC_DEMOS_DOMAIN}
      - NUXT_PUBLIC_TYPESENSE_HOST=${NUXT_PUBLIC_TYPESENSE_HOST}
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Development Compose

docker-compose.dev.yml
version: '3.8'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - .:/opt/5stack
      - /opt/5stack/node_modules
    environment:
      - NODE_ENV=development
    env_file:
      - .env
    restart: unless-stopped

Running with Compose

Production:
docker-compose up -d
Development:
docker-compose -f docker-compose.dev.yml up
Rebuild and start:
docker-compose up --build
View logs:
docker-compose logs -f web
Stop services:
docker-compose down

Image Optimization

Multi-stage Build Benefits

The production Dockerfile uses multi-stage builds for:
  1. Smaller image size - Only runtime files in final image
  2. Faster builds - Cached dependency layers
  3. Security - No build tools in production image
  4. Consistency - Same build process everywhere

Build Cache Optimization

Order of operations matters for Docker layer caching:
# Copy dependency files first (changes infrequently)
COPY package.json yarn.lock .yarnrc.yml ./

# Install dependencies (cached unless deps change)
RUN yarn install --immutable

# Copy source code last (changes frequently)
COPY . .

Image Size

Typical image sizes:
  • Development: ~800MB (includes dev dependencies)
  • Production: ~200MB (standalone output only)

Environment Configuration

Build-time vs Runtime Variables

Nuxt public runtime config variables must be available at build time for proper code generation.
Build-time (must be set during yarn build):
  • All NUXT_PUBLIC_* variables
  • Used for code generation and optimization
Runtime (can be set when starting container):
  • Server-side only variables
  • Override values without rebuilding

Passing Environment Variables

Multiple methods to provide environment variables:
  1. Command line:
    docker run -e VAR=value ...
    
  2. Environment file:
    docker run --env-file .env ...
    
  3. Docker Compose:
    environment:
      - VAR=value
    # or
    env_file:
      - .env
    

Container Registry

Tagging for Registry

# Tag for Docker Hub
docker tag 5stack:latest username/5stack:latest
docker tag 5stack:latest username/5stack:v1.0.0

# Tag for private registry
docker tag 5stack:latest registry.example.com/5stack:latest

Pushing to Registry

# Docker Hub
docker push username/5stack:latest
docker push username/5stack:v1.0.0

# Private registry
docker push registry.example.com/5stack:latest

Pulling from Registry

# Docker Hub
docker pull username/5stack:latest

# Private registry
docker pull registry.example.com/5stack:latest

Health Checks

Add health checks to monitor container status:
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
  CMD node -e "require('http').get('http://localhost:3000', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
In Docker Compose:
healthcheck:
  test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 40s

Resource Limits

Set resource constraints for production:
docker run \
  --memory="512m" \
  --cpus="1.0" \
  -p 3000:3000 \
  5stack:latest
In Docker Compose:
services:
  web:
    image: 5stack:latest
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M

Troubleshooting

Common causes:
  • Missing .yarnrc.yml file
  • Network issues during dependency download
  • Incompatible Node.js version
Solutions:
# Use build args for proxy
docker build --build-arg HTTP_PROXY=http://proxy.example.com:8080 .

# Clear build cache
docker build --no-cache -t 5stack:latest .
Check container logs:
docker logs <container-id>
Common issues:
  • Missing environment variables
  • Port already in use
  • Insufficient memory
Ensure volume mounts are correct:
docker run \
  -v $(pwd):/opt/5stack \
  -v /opt/5stack/node_modules \
  5stack:dev
The second volume mount prevents node_modules from being overwritten.
Optimization tips:
  • Use .dockerignore to exclude unnecessary files
  • Remove dev dependencies in production builds
  • Use alpine base images
  • Leverage multi-stage builds properly

Production Deployment Platforms

Kubernetes

Deploy to Kubernetes clusters with container orchestration

AWS ECS

Run containers on Amazon Elastic Container Service

Google Cloud Run

Serverless container platform with automatic scaling

Azure Container Instances

Deploy containers on Microsoft Azure

Next Steps

Environment Variables

Configure environment variables

Cloudflare Workers

Deploy serverless functions

Local Setup

Set up local development

System Monitoring

Monitor application health

Build docs developers (and LLMs) love