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 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
- Production Deployment - Production-grade setup
- Local Development - Development workflow
- Support - Get help
Docker provides a solid foundation for deploying Foldsite anywhere. From development to production, containers ensure consistency and reliability.