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:
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
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/.
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
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
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:
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:
Image Optimization
Multi-stage Build Benefits
The production Dockerfile uses multi-stage builds for:
Smaller image size - Only runtime files in final image
Faster builds - Cached dependency layers
Security - No build tools in production image
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:
Command line :
docker run -e VAR=value ...
Environment file :
docker run --env-file .env ...
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
Build fails at yarn install
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 .
Container exits immediately
Hot reload not working in development
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
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