managarten/docs/DOCKER_GUIDE.md
Till JS 22a73943e1 chore: complete ManaCore → Mana rename (docs, go modules, plists, images)
Final cleanup of references missed in previous rename commits:

- Dockerfiles: PUBLIC_MANA_CORE_AUTH_URL → PUBLIC_MANA_AUTH_URL
- Go modules: github.com/manacore/* → github.com/mana/* (7 go.mod files)
- launchd plists: com.manacore.* → com.mana.* (14 files renamed + content)
- Image assets: *_Manacore_AI_Credits* → *_Mana_AI_Credits* (11 files)
- .env.example files: ManaCore brand strings → Mana
- .prettierignore: stale apps/manacore/* paths → apps/mana/*
- Markdown docs (CLAUDE.md, /docs/*): mana-core-auth → mana-auth, etc.

Excluded from rename: .claude/, devlog/, manascore/ (historical content),
client testimonials, blueprints, npm package refs (@mana-core/*).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:26:10 +02:00

10 KiB

Docker Guide

Comprehensive guide for working with Docker in the mana-monorepo.

Table of Contents

Overview

The monorepo uses Docker for:

  • Development: Local service orchestration
  • CI/CD: Automated builds and tests
  • Production: Deployment and scaling

Image Strategy

All images use:

  • Multi-stage builds: Smaller production images
  • Alpine Linux: Minimal base images
  • Non-root users: Enhanced security
  • Health checks: Automatic monitoring
  • Layer caching: Faster builds

Docker Templates

Templates are located in docker/templates/. Use these as starting points for new services.

NestJS Backend Template

File: docker/templates/Dockerfile.nestjs

Usage:

# Copy template
cp docker/templates/Dockerfile.nestjs apps/myproject/apps/backend/Dockerfile

# Customize for your service

Build Arguments:

  • SERVICE_PATH: Path to service (e.g., apps/chat/apps/backend)
  • PORT: Service port (default: 3000)
  • HEALTH_PATH: Health check endpoint (default: /health)

Example:

docker build \
  --build-arg SERVICE_PATH=apps/chat/apps/backend \
  --build-arg PORT=3002 \
  --build-arg HEALTH_PATH=/api/health \
  -t chat-backend:latest \
  -f docker/templates/Dockerfile.nestjs \
  .

SvelteKit Web Template

File: docker/templates/Dockerfile.sveltekit

Features:

  • SSR support
  • Environment variable injection
  • Static asset optimization
  • Health endpoint

Usage:

docker build \
  --build-arg SERVICE_PATH=apps/chat/apps/web \
  --build-arg PORT=3000 \
  -t chat-web:latest \
  -f docker/templates/Dockerfile.sveltekit \
  .

Astro Landing Page Template

File: docker/templates/Dockerfile.astro

Features:

  • Static site serving with Nginx
  • Gzip compression
  • Security headers
  • Asset caching

Nginx Configuration: docker/nginx/astro.conf

Usage:

docker build \
  --build-arg SERVICE_PATH=apps/chat/apps/landing \
  -t chat-landing:latest \
  -f docker/templates/Dockerfile.astro \
  .

Building Images

Local Development Builds

# Build single service
docker build -t service-name:dev -f apps/project/apps/service/Dockerfile .

# Build with cache
docker build --cache-from service-name:latest -t service-name:dev .

# Build without cache
docker build --no-cache -t service-name:dev .

Production Builds

# Build for production
docker build \
  --build-arg NODE_ENV=production \
  -t service-name:latest \
  -f Dockerfile .

# Build for multiple platforms
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t service-name:latest \
  .

Using Build Script

# Build all services
./scripts/deploy/build-and-push.sh all latest

# Build specific service
./scripts/deploy/build-and-push.sh chat-backend v1.0.0

# Build without pushing
DOCKER_PUSH=false ./scripts/deploy/build-and-push.sh chat-backend dev

Running Containers

Run Single Container

# Run with environment file
docker run -d \
  --name chat-backend \
  --env-file .env.production \
  -p 3002:3002 \
  chat-backend:latest

# Run with environment variables
docker run -d \
  --name chat-backend \
  -e NODE_ENV=production \
  -e PORT=3002 \
  -p 3002:3002 \
  chat-backend:latest

# Run with volume mount
docker run -d \
  --name chat-backend \
  -v $(pwd)/logs:/app/logs \
  -p 3002:3002 \
  chat-backend:latest

Interactive Debugging

# Run with shell
docker run -it --rm chat-backend:latest /bin/sh

# Execute command in running container
docker exec -it chat-backend sh

# View logs
docker logs -f chat-backend

# View last 100 lines
docker logs --tail=100 chat-backend

Health Checks

# Check container health
docker inspect --format='{{.State.Health.Status}}' chat-backend

# View health check logs
docker inspect --format='{{range .State.Health.Log}}{{.Output}}{{end}}' chat-backend

Docker Compose

Development Environment

File: docker-compose.dev.yml

Start services for local development:

# Start all services
pnpm run docker:up

# Start with specific profile
pnpm run docker:up:auth
pnpm run docker:up:chat

# View logs
pnpm run docker:logs

# Stop all services
pnpm run docker:down

Staging Environment

File: docker-compose.staging.yml

# Deploy to staging
docker compose -f docker-compose.staging.yml up -d

# Scale service
docker compose -f docker-compose.staging.yml up -d --scale chat-backend=3

# View status
docker compose -f docker-compose.staging.yml ps

# View logs
docker compose -f docker-compose.staging.yml logs -f chat-backend

Production Environment

File: docker-compose.production.yml

# Deploy to production
docker compose -f docker-compose.production.yml up -d

# Rolling update
docker compose -f docker-compose.production.yml up -d --no-deps service-name

# Zero-downtime deployment
docker compose up -d --scale service=2 service
sleep 30
docker compose up -d --scale service=1 service

Common Commands

# Start services
docker compose up -d

# Stop services
docker compose stop

# Restart service
docker compose restart service-name

# View logs
docker compose logs -f

# Execute command
docker compose exec service-name sh

# Remove all containers
docker compose down

# Remove containers and volumes
docker compose down -v

Best Practices

1. Optimize Layer Caching

Order Dockerfile commands from least to most frequently changing:

# Good
COPY package.json pnpm-lock.yaml ./
RUN pnpm install
COPY . .

# Bad (cache invalidated on every code change)
COPY . .
RUN pnpm install

2. Use .dockerignore

Create .dockerignore to exclude unnecessary files:

node_modules
dist
.git
.env
*.log

3. Multi-Stage Builds

Always use multi-stage builds for smaller images:

# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY . .
RUN pnpm install && pnpm build

# Production stage
FROM node:20-alpine AS production
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/main.js"]

4. Security Best Practices

# Use non-root user
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nestjs -u 1001
USER nestjs

# Don't include secrets
# Use environment variables or Docker secrets

# Scan images for vulnerabilities
docker scan image-name:latest

5. Health Checks

Always include health checks:

HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

6. Resource Limits

Set resource limits in docker-compose:

services:
  backend:
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M

7. Logging

Configure logging drivers:

services:
  backend:
    logging:
      driver: 'json-file'
      options:
        max-size: '10m'
        max-file: '3'

8. Environment Variables

Use environment files:

# .env.production
NODE_ENV=production
PORT=3000
DATABASE_URL=postgresql://...
services:
  backend:
    env_file:
      - .env.production

Troubleshooting

Container Won't Start

Issue: Container exits immediately

Debug:

# View container logs
docker logs container-name

# Check exit code
docker inspect --format='{{.State.ExitCode}}' container-name

# Run interactively
docker run -it --rm image-name sh

Out of Disk Space

Issue: Docker runs out of disk space

Solution:

# Check disk usage
docker system df

# Remove unused containers
docker container prune

# Remove unused images
docker image prune -a

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

# Remove specific resources
docker rm $(docker ps -aq)
docker rmi $(docker images -q)

Build Fails

Issue: Docker build fails

Debug:

# Build with verbose output
docker build --progress=plain --no-cache -t image-name .

# Check build context
docker build --dry-run .

# Build specific stage
docker build --target builder -t image-name .

Network Issues

Issue: Containers can't communicate

Debug:

# List networks
docker network ls

# Inspect network
docker network inspect bridge

# Test connectivity
docker exec container1 ping container2

# Check DNS
docker exec container1 nslookup container2

Performance Issues

Issue: Container runs slowly

Debug:

# Check resource usage
docker stats

# Check container processes
docker top container-name

# Analyze image layers
docker history image-name

Permission Issues

Issue: Permission denied errors

Solution:

# Check file ownership
docker exec container-name ls -la /app

# Fix ownership in Dockerfile
RUN chown -R nodejs:nodejs /app
USER nodejs

Environment Variables Not Working

Issue: Env vars not available in container

Debug:

# Check environment
docker exec container-name env

# Verify env file
cat .env.production

# Test with explicit vars
docker run -e VAR=value image-name

Advanced Topics

Docker BuildKit

Enable for better builds:

# Enable BuildKit
export DOCKER_BUILDKIT=1

# Build with BuildKit
docker build .

# Use buildx for multi-platform
docker buildx build --platform linux/amd64,linux/arm64 .

Docker Secrets

For sensitive data:

# Create secret
echo "secret-value" | docker secret create my_secret -

# Use in service
docker service create \
  --secret my_secret \
  --name my-service \
  image-name

Docker Volumes

Persist data:

# Create volume
docker volume create my-data

# Use volume
docker run -v my-data:/app/data image-name

# Backup volume
docker run --rm -v my-data:/data -v $(pwd):/backup alpine tar czf /backup/backup.tar.gz /data

Custom Networks

Isolate services:

# Create network
docker network create --driver bridge my-network

# Run container on network
docker run --network my-network image-name

# Connect existing container
docker network connect my-network container-name

Resources