Files
foldsite/docs/content/deployment/docker.md
Tanishq Dubey ad81d7f3db
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 52s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 1m1s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 5m50s
docs refactor
2025-10-09 18:21:23 -04:00

14 KiB

version, date, author, title, description, summary, quick_tips
version date author title description summary quick_tips
1.0 2025-01-15 DWS Foldsite Team Docker Deployment Running Foldsite in Docker containers Complete guide to deploying Foldsite with Docker for consistent, isolated, and portable deployments.
Docker ensures consistent environments across development and production
Use docker-compose for easy multi-container setup
Mount content as volumes for live updates without rebuilding

Docker Deployment

Docker provides isolated, reproducible deployments of Foldsite. Perfect for testing, staging, and production environments.

Why Docker?

Benefits:

  • Consistency - Same environment everywhere
  • Isolation - Dependencies don't conflict with system
  • Portability - Run anywhere Docker runs
  • Easy deployment - Single command to start
  • Version control - Docker images are versioned

Use cases:

  • Team development (everyone has same environment)
  • Staging environments before production
  • Production deployments
  • CI/CD pipelines
  • Cloud platform deployments

Prerequisites

Install Docker

macOS:

# Download Docker Desktop from docker.com
# Or use Homebrew
brew install --cask docker

Linux (Ubuntu/Debian):

# Update package index
sudo apt update

# Install Docker
sudo apt install docker.io docker-compose

# Add your user to docker group
sudo usermod -aG docker $USER

# Log out and back in for group changes

Windows:

# Download Docker Desktop from docker.com
# Requires WSL2

Verify installation:

docker --version
docker-compose --version

Quick Start with Docker Compose

Step 1: Create docker-compose.yml

In your Foldsite directory:

version: '3.8'

services:
  foldsite:
    image: python:3.11-slim
    container_name: foldsite
    working_dir: /app
    command: >
      sh -c "pip install -r requirements.txt &&
             python main.py --config config.toml"
    ports:
      - "8081:8081"
    volumes:
      - .:/app
      - ./my-site/content:/app/content
      - ./my-site/templates:/app/templates
      - ./my-site/styles:/app/styles
    environment:
      - PYTHONUNBUFFERED=1
    restart: unless-stopped

Step 2: Create config.toml for Docker

[paths]
content_dir = "/app/content"
templates_dir = "/app/templates"
styles_dir = "/app/styles"

[server]
listen_address = "0.0.0.0"  # Important: bind to all interfaces
listen_port = 8081
admin_browser = false
max_threads = 4
debug = false
access_log = true

Step 3: Start Container

# Start in background
docker-compose up -d

# View logs
docker-compose logs -f

# Stop
docker-compose down

Visit http://localhost:8081 to see your site!

Building a Custom Docker Image

For production, build a dedicated Foldsite image:

Create Dockerfile

# Dockerfile
FROM python:3.11-slim

# Set working directory
WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    && rm -rf /var/lib/apt/lists/*

# Copy requirements first (for caching)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY . .

# Create directories for content
RUN mkdir -p /content /templates /styles

# Expose port
EXPOSE 8081

# Run application
CMD ["python", "main.py", "--config", "/app/config.toml"]

Build Image

# Build image
docker build -t foldsite:latest .

# Tag for versioning
docker tag foldsite:latest foldsite:1.0.0

Run Container

docker run -d \
  --name foldsite \
  -p 8081:8081 \
  -v $(pwd)/my-site/content:/content \
  -v $(pwd)/my-site/templates:/templates \
  -v $(pwd)/my-site/styles:/styles \
  foldsite:latest

Development with Docker

Hot Reload Setup

Mount your code as volumes for live updates:

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

services:
  foldsite:
    build: .
    container_name: foldsite-dev
    ports:
      - "8081:8081"
    volumes:
      # Mount everything for development
      - .:/app
      - ./my-site/content:/app/content
      - ./my-site/templates:/app/templates
      - ./my-site/styles:/app/styles
    environment:
      - PYTHONUNBUFFERED=1
      - FLASK_ENV=development
    command: >
      sh -c "pip install -r requirements.txt &&
             python main.py --config config.toml"

Usage:

# Start development environment
docker-compose -f docker-compose.dev.yml up

# Changes to content, templates, and styles appear immediately
# Code changes require restart

Interactive Development

Run commands inside container:

# Start bash session in running container
docker exec -it foldsite bash

# Inside container, you can:
python main.py --config config.toml
pip install new-package
ls /app/content

Production Docker Setup

Multi-Stage Build

Optimize image size with multi-stage build:

# Dockerfile.production
# Stage 1: Build dependencies
FROM python:3.11-slim as builder

WORKDIR /app

# Install build dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    && rm -rf /var/lib/apt/lists/*

# Install Python dependencies
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

# Stage 2: Runtime
FROM python:3.11-slim

WORKDIR /app

# Copy Python dependencies from builder
COPY --from=builder /root/.local /root/.local

# Copy application
COPY . .

# Create non-root user
RUN useradd -m -u 1000 foldsite && \
    chown -R foldsite:foldsite /app

# Switch to non-root user
USER foldsite

# Make sure scripts in .local are usable
ENV PATH=/root/.local/bin:$PATH

EXPOSE 8081

# Use Gunicorn for production
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8081", "main:app"]

Production docker-compose.yml

version: '3.8'

services:
  foldsite:
    build:
      context: .
      dockerfile: Dockerfile.production
    container_name: foldsite-prod
    ports:
      - "8081:8081"
    volumes:
      - ./content:/app/content:ro  # Read-only
      - ./templates:/app/templates:ro
      - ./styles:/app/styles:ro
    environment:
      - PYTHONUNBUFFERED=1
    restart: always
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8081/"]
      interval: 30s
      timeout: 10s
      retries: 3

Docker Compose Examples

With Nginx Reverse Proxy

version: '3.8'

services:
  foldsite:
    build: .
    container_name: foldsite
    expose:
      - "8081"
    volumes:
      - ./content:/app/content:ro
      - ./templates:/app/templates:ro
      - ./styles:/app/styles:ro
    restart: always

  nginx:
    image: nginx:alpine
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - foldsite
    restart: always

nginx.conf:

events {
    worker_connections 1024;
}

http {
    upstream foldsite {
        server foldsite:8081;
    }

    server {
        listen 80;
        server_name your-domain.com;

        location / {
            proxy_pass http://foldsite;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

        # Cache static assets
        location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
            proxy_pass http://foldsite;
            expires 30d;
            add_header Cache-Control "public, immutable";
        }
    }
}

Multiple Sites

Run multiple Foldsite instances:

version: '3.8'

services:
  blog:
    build: .
    ports:
      - "8081:8081"
    volumes:
      - ./blog/content:/app/content
      - ./blog/templates:/app/templates
      - ./blog/styles:/app/styles
    restart: always

  portfolio:
    build: .
    ports:
      - "8082:8081"
    volumes:
      - ./portfolio/content:/app/content
      - ./portfolio/templates:/app/templates
      - ./portfolio/styles:/app/styles
    restart: always

Volume Management

Content Volumes

Development - Mount host directories:

volumes:
  - ./my-site/content:/app/content
  - ./my-site/templates:/app/templates
  - ./my-site/styles:/app/styles

Production - Read-only mounts:

volumes:
  - ./content:/app/content:ro
  - ./templates:/app/templates:ro
  - ./styles:/app/styles:ro

Named Volumes

For persistent data:

services:
  foldsite:
    volumes:
      - content-data:/app/content
      - templates-data:/app/templates

volumes:
  content-data:
  templates-data:

Backup named volumes:

# Backup
docker run --rm \
  -v foldsite_content-data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/content-backup.tar.gz -C /data .

# Restore
docker run --rm \
  -v foldsite_content-data:/data \
  -v $(pwd):/backup \
  alpine tar xzf /backup/content-backup.tar.gz -C /data

Environment Variables

Pass configuration via environment:

services:
  foldsite:
    environment:
      - FOLDSITE_DEBUG=false
      - FOLDSITE_PORT=8081
      - FOLDSITE_MAX_THREADS=4

Use in config:

# In a config loader
import os

debug = os.getenv('FOLDSITE_DEBUG', 'false').lower() == 'true'
port = int(os.getenv('FOLDSITE_PORT', '8081'))

Common Docker Commands

Container Management

# Start containers
docker-compose up -d

# Stop containers
docker-compose down

# Restart
docker-compose restart

# View logs
docker-compose logs -f

# View logs for specific service
docker-compose logs -f foldsite

# Exec into running container
docker exec -it foldsite bash

# View running containers
docker ps

# View all containers (including stopped)
docker ps -a

Image Management

# Build image
docker-compose build

# Pull images
docker-compose pull

# List images
docker images

# Remove unused images
docker image prune

# Remove all unused data
docker system prune -a

Debugging

# Check container logs
docker logs foldsite

# Follow logs
docker logs -f foldsite

# Inspect container
docker inspect foldsite

# View container stats
docker stats foldsite

# Check container health
docker ps --filter health=healthy

Troubleshooting

Port Already in Use

Error: port is already allocated

Solution: Change port mapping:

ports:
  - "8082:8081"  # Map to different host port

Permission Errors

PermissionError: [Errno 13] Permission denied

Solution: Fix volume permissions:

# Fix ownership
sudo chown -R $USER:$USER ./my-site

# Or run container as your user
docker run --user $(id -u):$(id -g) ...

Container Won't Start

# Check logs
docker-compose logs

# Common issues:
# 1. Missing requirements.txt
# 2. Wrong working directory
# 3. Port conflicts
# 4. Volume mount errors

Changes Not Appearing

Content changes:

  • Should appear immediately (volumes mounted)
  • Try hard refresh in browser

Code changes:

  • Require container restart: docker-compose restart

Template changes:

  • Should appear immediately
  • Check volume mounts are correct

Container Crashes

# View exit reason
docker ps -a

# Check logs
docker logs foldsite

# Try running interactively
docker run -it foldsite bash

Performance Optimization

Resource Limits

Limit container resources:

services:
  foldsite:
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 512M

Build Cache

Speed up builds:

# Use BuildKit
DOCKER_BUILDKIT=1 docker build .

# Cache from registry
docker build --cache-from myregistry/foldsite:latest .

Layer Optimization

Order Dockerfile for better caching:

# Dependencies first (change rarely)
COPY requirements.txt .
RUN pip install -r requirements.txt

# Code last (changes often)
COPY . .

CI/CD Integration

GitHub Actions Example

# .github/workflows/docker.yml
name: Build Docker Image

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Build image
        run: docker build -t foldsite:${{ github.sha }} .

      - name: Test
        run: |
          docker run -d --name test foldsite:${{ github.sha }}
          docker logs test
          docker stop test

Cloud Platform Deployment

Deploy to AWS ECS

# Build and push to ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com
docker tag foldsite:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/foldsite:latest
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/foldsite:latest

Deploy to Google Cloud Run

# Build and push to GCR
gcloud builds submit --tag gcr.io/PROJECT_ID/foldsite
gcloud run deploy --image gcr.io/PROJECT_ID/foldsite --platform managed

Deploy to Azure Container Instances

# Create container instance
az container create \
  --resource-group myResourceGroup \
  --name foldsite \
  --image myregistry.azurecr.io/foldsite:latest \
  --ports 8081

Next Steps

Docker provides a solid foundation for deploying Foldsite anywhere. From development to production, containers ensure consistency and reliability.