/ opengrammar / docs / 06-docker-self-hosting.md
swadhinbiswas docs: add Docker self-hosting quick start guide Β· 3/14/2026
cbf5200
526 lines Β· 9.7 KB
Raw Download

🐳 Docker Self-Hosting Guide

Run OpenGrammar locally with Docker and optional local LLM support (Ollama).


🎯 Why Self-Host with Docker?

Benefit Description
Complete Privacy All data stays on your machine
Free No API costs (with local LLM)
Offline Works without internet
Full Control Customize everything
No Rate Limits Use as much as you want

πŸ“‹ Prerequisites

  • Docker (v20.10+)
  • Docker Compose (usually included with Docker)
  • 4GB+ RAM (for local LLM)
  • NVIDIA GPU (optional, for faster LLM inference)

πŸš€ Quick Start

Option 1: Backend Only (Use Cloud APIs)

cd opengrammar/opengrammar

# Create environment file
cat > .env << EOF
PORT=8787
NODE_ENV=production
GROQ_API_KEY=your_groq_key
OPENAI_API_KEY=your_openai_key
EOF

# Start backend
docker-compose up -d opengrammar-backend

# Check status
docker-compose ps

# View logs
docker-compose logs -f opengrammar-backend

Option 2: Backend + Ollama (Local LLM)

cd opengrammar/opengrammar

# Start everything (requires NVIDIA GPU)
docker-compose --profile local-llm up -d

# Check status
docker-compose ps

# View all logs
docker-compose logs -f

πŸ”§ Docker Compose Configuration

Complete docker-compose.yml

version: '3.8'

services:
  # OpenGrammar Backend
  opengrammar-backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    container_name: opengrammar-backend
    restart: unless-stopped
    ports:
      - "8787:8787"
    environment:
      - NODE_ENV=production
      - PORT=8787
      - GROQ_API_KEY=${GROQ_API_KEY:-}
      - OPENAI_API_KEY=${OPENAI_API_KEY:-}
      - OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
      - TOGETHER_API_KEY=${TOGETHER_API_KEY:-}
      - OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://ollama:11434/v1}
      - DEBUG=${DEBUG:-false}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8787/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    networks:
      - opengrammar-network
    depends_on:
      - ollama
    volumes:
      - ./backend/logs:/app/logs

  # Ollama (Local LLM)
  ollama:
    image: ollama/ollama:latest
    container_name: opengrammar-ollama
    restart: unless-stopped
    profiles:
      - local-llm
    ports:
      - "11434:11434"
    volumes:
      - ollama_data:/root/.ollama
    networks:
      - opengrammar-network
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

  # Open WebUI (Optional - for testing Ollama)
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: opengrammar-webui
    restart: unless-stopped
    profiles:
      - local-llm
    ports:
      - "3000:8080"
    environment:
      - OLLAMA_BASE_URL=http://ollama:11434
    networks:
      - opengrammar-network
    depends_on:
      - ollama
    volumes:
      - open-webui_data:/app/backend/data

networks:
  opengrammar-network:
    driver: bridge

volumes:
  ollama_data:
  open-webui_data:

πŸ€– Local LLM Setup with Ollama

Step 1: Start Ollama Container

docker-compose --profile local-llm up -d ollama

Step 2: Pull Grammar-Focused Models

# Enter Ollama container
docker exec -it opengrammar-ollama bash

# Pull models (inside container)
ollama pull qwen2.5:0.5b      # Ultra fast, 400MB
ollama pull qwen2.5:1.5b      # Balanced, 1GB
ollama pull phi4-mini:3.8b    # Great quality, 2.5GB
ollama pull llama3.2:3b       # Good all-rounder, 2GB

# Exit container
exit

Step 3: Test Ollama

# Test from host
curl http://localhost:11434/api/tags

# Test model
curl http://localhost:11434/api/generate -d '{
  "model": "qwen2.5:1.5b",
  "prompt": "Fix this grammar: me and him went to store"
}'

Step 4: Configure OpenGrammar

  1. Click extension icon β†’ Settings
  2. Provider: Ollama (Local)
  3. Base URL: http://localhost:11434/v1
  4. Model: qwen2.5:1.5b
  5. API Key: (leave empty)
  6. Backend URL: http://localhost:8787

🎯 Model Recommendations

For Grammar Checking

Model Size RAM Speed Quality Best For
qwen2.5:0.5b 400MB 1GB ⚑⚑⚑⚑⚑ ⭐⭐⭐ Fast basic checks
qwen2.5:1.5b 1GB 2GB ⚑⚑⚑⚑ ⭐⭐⭐⭐ Balanced
phi4-mini:3.8b 2.5GB 4GB ⚑⚑⚑ ⭐⭐⭐⭐⭐ Best quality
llama3.2:3b 2GB 3GB ⚑⚑⚑⚑ ⭐⭐⭐⭐ Good balance

For GPU Acceleration

If you have an NVIDIA GPU:

# High quality with GPU
ollama pull llama3.2:7b       # 4GB, requires 8GB+ GPU
ollama pull mistral:7b        # 4GB, requires 8GB+ GPU
ollama pull mixtral:8x7b      # 26GB, requires 24GB+ GPU

πŸ”§ Advanced Configuration

Custom Backend Port

# docker-compose.yml
ports:
  - "9000:8787"  # Change 8787 to 9000

Enable GPU Support

# For NVIDIA GPUs
ollama:
  deploy:
    resources:
      reservations:
        devices:
          - driver: nvidia
            count: all
            capabilities: [gpu]

Persistent Logs

opengrammar-backend:
  volumes:
    - ./logs:/app/logs

Network Isolation

networks:
  opengrammar-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.28.0.0/16

πŸ“Š Performance Benchmarks

Local LLM (RTX 4090)

Model Tokens/sec Grammar Accuracy RAM VRAM
qwen2.5:0.5b ~100 75% 1GB 1GB
qwen2.5:1.5b ~80 82% 2GB 2GB
phi4-mini:3.8b ~50 88% 4GB 4GB
llama3.2:7b ~30 90% 8GB 8GB

Cloud APIs (via Docker)

Model Latency Grammar Accuracy Cost/1K requests
gpt-4o-mini ~1s 95% $0.15
llama-3.1-70b (Groq) ~200ms 92% Free (tier)
claude-3.5-sonnet ~2s 96% $3.00

πŸ›‘οΈ Security Considerations

1. Network Isolation

networks:
  opengrammar-network:
    internal: true  # No external access

2. Environment Variables

Never commit .env file:

echo ".env" >> .gitignore

3. API Key Rotation

# Generate new keys periodically
openssl rand -hex 32

4. Container Security

security_opt:
  - no-new-privileges:true
read_only: true
tmpfs:
  - /tmp

πŸ“ˆ Monitoring & Maintenance

View Logs

# All services
docker-compose logs -f

# Specific service
docker-compose logs -f opengrammar-backend

# Last 100 lines
docker-compose logs --tail=100 opengrammar-backend

Check Health

# Backend health
curl http://localhost:8787/health

# Ollama status
curl http://localhost:11434/api/tags

# Container status
docker-compose ps

Update Containers

# Pull latest images
docker-compose pull

# Recreate containers
docker-compose up -d --force-recreate

# Clean up old images
docker image prune -f

Backup Data

# Backup Ollama models
docker run --rm \
  -v opengrammar_ollama_data:/data \
  -v $(pwd)/backup:/backup \
  alpine tar czf /backup/ollama-backup.tar.gz /data

# Backup settings
docker-compose exec opengrammar-backend \
  cat /app/data/settings.json > backup-settings.json

πŸ”„ Troubleshooting

Container Won't Start

# Check logs
docker-compose logs opengrammar-backend

# Test configuration
docker-compose config

# Check port conflict
lsof -i :8787
lsof -i :11434

Ollama Connection Failed

# Check Ollama is running
docker-compose ps ollama

# Test connection
docker-compose exec opengrammar-backend curl http://ollama:11434/api/tags

# Restart Ollama
docker-compose restart ollama

GPU Not Working

# Check NVIDIA Container Toolkit
nvidia-container-cli info

# Verify GPU access
docker exec -it opengrammar-ollama nvidia-smi

# Update Docker Compose
docker-compose version

High Memory Usage

# Check container memory
docker stats

# Limit Ollama memory
ollama:
  deploy:
    resources:
      limits:
        memory: 4G

Slow Performance

# Check CPU usage
docker stats

# Use smaller model
ollama pull qwen2.5:0.5b

# Enable GPU (if available)
# See GPU configuration above

πŸš€ Production Deployment

Docker Swarm

# docker-stack.yml
version: '3.8'

services:
  opengrammar-backend:
    image: opengrammar-backend:latest
    ports:
      - "8787:8787"
    environment:
      - NODE_ENV=production
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '1'
          memory: 512M
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8787/health"]
      interval: 30s
      timeout: 10s
      retries: 3

Deploy:

docker stack deploy -c docker-stack.yml opengrammar

Kubernetes

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: opengrammar-backend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: opengrammar-backend
  template:
    metadata:
      labels:
        app: opengrammar-backend
    spec:
      containers:
      - name: backend
        image: opengrammar-backend:latest
        ports:
        - containerPort: 8787
        env:
        - name: NODE_ENV
          value: "production"
        livenessProbe:
          httpGet:
            path: /health
            port: 8787
          initialDelaySeconds: 30
          periodSeconds: 10

πŸ“š Related Documentation


Your self-hosted OpenGrammar instance is ready! Happy writing! ✨