major-domo-v2/DOCKER.md
Cal Corum 5924249481 CLAUDE: Add comprehensive Docker deployment infrastructure
Implements production-ready Docker setup with multi-stage builds and
separate development/production configurations.

New Files:
- Dockerfile: Multi-stage build with Python 3.13
  * Builder stage: Compiles dependencies with build tools
  * Runtime stage: Minimal image (~150-200MB) with non-root user
  * Health checks and security hardening
- docker-compose.yml: Production config (pulls from Docker Hub)
  * Image: manticorum67/major-domo-discordapp:latest
  * Resource limits: 512MB RAM, 1 CPU
  * Volumes: /app/data (ro), /app/logs (rw)
- docker-compose.dev.yml: Development config (builds locally)
  * Higher resource limits: 1GB RAM, 2 CPU
  * DEBUG log level by default
- .dockerignore: Excludes unnecessary files from build context
- build-and-push.sh: Interactive build/push script for Docker Hub
- DOCKER.md: Comprehensive deployment guide (13K)
- BUILD_AND_PUSH.md: Docker Hub build/push guide (7.7K)

Configuration Updates:
- config.py: Updated sheets_credentials_path to /app/data location
- requirements.txt: Pinned all package versions for reproducibility
- .env.example: Added Docker-specific configuration

Key Features:
- Multi-stage build for optimized image size
- Non-root user (botuser, UID 1000) for security
- Separate dev/prod compose files
- Volume mounts for persistence (/app/data, /app/logs)
- Health checks and automatic restarts
- Resource limits and log rotation
- Docker Hub integration for production deployments

Docker Hub Repository: manticorum67/major-domo-discordapp

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 00:54:56 -05:00

569 lines
12 KiB
Markdown

# Docker Deployment Guide
This guide covers deploying the Discord Bot v2.0 using Docker and Docker Compose.
## Prerequisites
- Docker 20.10+ installed
- Docker Compose 2.0+ installed
- Google Sheets service account credentials JSON file
- Access to the database API (running on a separate host)
## Deployment Modes
### Production (Recommended)
Uses `docker-compose.yml` - pulls pre-built image from Docker Hub
### Development
Uses `docker-compose.dev.yml` - builds image locally from source
---
## Quick Start (Production)
Deploy using pre-built image from Docker Hub:
### 1. Prepare Configuration
```bash
# Copy the example environment file
cp .env.example .env
# Edit .env with your actual values
nano .env
```
**Required environment variables:**
- `BOT_TOKEN` - Your Discord bot token
- `API_TOKEN` - Database API authentication token
- `DB_URL` - Database API endpoint URL
- `GUILD_ID` - Your Discord server ID
### 2. Prepare Data Directory
```bash
# Create data directory for Google Sheets credentials
mkdir -p data
# Copy your Google Sheets credentials file
cp /path/to/your/credentials.json data/major-domo-service-creds.json
# Set proper permissions (read-only)
chmod 444 data/major-domo-service-creds.json
```
### 3. Create Logs Directory
```bash
# Create logs directory (will be mounted as volume)
mkdir -p logs
```
### 4. Pull and Run
```bash
# Pull latest image from Docker Hub
docker-compose pull
# Start the bot
docker-compose up -d
# View logs
docker-compose logs -f discord-bot
```
---
## Development Setup
Build and run locally with source code:
### 1. Complete steps 1-3 from Production setup above
### 2. Build and Run
```bash
# Build the Docker image locally
docker-compose -f docker-compose.dev.yml build
# Start the bot
docker-compose -f docker-compose.dev.yml up -d
# View logs
docker-compose -f docker-compose.dev.yml logs -f discord-bot
```
## Docker Commands
### Production Commands
```bash
# Pull latest image from Docker Hub
docker-compose pull
# Start in detached mode
docker-compose up -d
# Start in foreground (see logs)
docker-compose up
# Restart the bot
docker-compose restart discord-bot
# Stop the bot
docker-compose stop discord-bot
# Stop and remove container
docker-compose down
```
### Development Commands
```bash
# Build the image locally
docker-compose -f docker-compose.dev.yml build
# Build without cache (force rebuild)
docker-compose -f docker-compose.dev.yml build --no-cache
# Start in detached mode
docker-compose -f docker-compose.dev.yml up -d
# Start and rebuild if needed
docker-compose -f docker-compose.dev.yml up -d --build
# Restart the bot
docker-compose -f docker-compose.dev.yml restart discord-bot
# Stop and remove
docker-compose -f docker-compose.dev.yml down
```
### Monitoring Commands
```bash
# View logs (follow mode)
docker-compose logs -f discord-bot
# View last 100 lines of logs
docker-compose logs --tail=100 discord-bot
# Check container status
docker-compose ps
# Check resource usage
docker stats major-domo-discord-bot-v2
# Execute commands inside container
docker-compose exec discord-bot bash
# View bot process
docker-compose exec discord-bot ps aux
```
### Maintenance Commands
```bash
# Pull latest code and restart
git pull
docker-compose up -d --build
# Clear logs
docker-compose exec discord-bot sh -c "rm -rf /logs/*.log"
# Restart after configuration changes
docker-compose down && docker-compose up -d
# View container health status
docker inspect --format='{{.State.Health.Status}}' major-domo-discord-bot-v2
```
## Directory Structure
```
discord-app-v2/
├── Dockerfile # Multi-stage build configuration
├── docker-compose.yml # Production: pulls from Docker Hub
├── docker-compose.dev.yml # Development: builds locally
├── .dockerignore # Files to exclude from image
├── .env # Environment configuration (not in git)
├── .env.example # Environment template
├── DOCKER.md # This deployment guide
├── BUILD_AND_PUSH.md # Guide for pushing to Docker Hub
├── data/ # Google Sheets credentials (mounted volume)
│ └── major-domo-service-creds.json
├── logs/ # Log files (mounted volume)
│ ├── discord_bot_v2.log
│ └── discord_bot_v2.json
└── ... (application code)
```
## Docker Hub Repository
**Repository**: `manticorum67/major-domo-discordapp`
**URL**: https://hub.docker.com/r/manticorum67/major-domo-discordapp
Production deployments pull from this repository. See `BUILD_AND_PUSH.md` for instructions on building and pushing new versions.
## Multi-Stage Build
The Dockerfile uses a multi-stage build for optimization:
### Stage 1: Builder
- Based on `python:3.13-slim`
- Installs build dependencies (gcc, g++)
- Compiles Python packages with C extensions
- Creates `.local` directory with all dependencies
### Stage 2: Runtime
- Based on `python:3.13-slim`
- Only includes runtime dependencies
- Copies compiled packages from builder
- Runs as non-root user (`botuser`)
- Final image size: ~150-200MB (vs ~500MB+ single-stage)
## Security Features
### Non-Root User
The bot runs as `botuser` (UID 1000) with restricted permissions:
```dockerfile
RUN groupadd -r botuser && \
useradd -r -g botuser -u 1000 -m -s /bin/bash botuser
USER botuser
```
### Read-Only Credentials
Mount credentials as read-only:
```yaml
volumes:
- ./data:/data:ro # ro = read-only
```
### Resource Limits
Default resource limits in docker-compose.yml:
- CPU: 1.0 cores max, 0.25 cores reserved
- Memory: 512MB max, 256MB reserved
Adjust based on your server capacity:
```yaml
deploy:
resources:
limits:
cpus: '2.0' # Increase for heavy workloads
memory: 1G # Increase if needed
```
## Volume Mounts
### Data Volume (Read-Only)
Contains Google Sheets credentials:
```yaml
volumes:
- ${SHEETS_CREDENTIALS_HOST_PATH:-./data}:/data:ro
```
### Logs Volume (Read-Write)
Persistent log storage:
```yaml
volumes:
- ${LOGS_HOST_PATH:-./logs}:/logs:rw
```
### Development Mode
Mount source code for live development:
```yaml
volumes:
- .:/app:ro # Uncomment in docker-compose.yml
```
## Health Checks
The bot includes a health check that runs every 60 seconds:
```dockerfile
HEALTHCHECK --interval=60s --timeout=10s --start-period=30s --retries=3 \
CMD python -c "import sys; sys.exit(0)" || exit 1
```
Check health status:
```bash
docker inspect --format='{{.State.Health.Status}}' major-domo-discord-bot-v2
```
## Logging
### Container Logs
Docker captures stdout/stderr:
```bash
docker-compose logs -f discord-bot
```
### Application Logs
Persistent logs in mounted volume:
- `/logs/discord_bot_v2.log` - Human-readable logs
- `/logs/discord_bot_v2.json` - Structured JSON logs
### Log Rotation
Docker manages log rotation:
```yaml
logging:
driver: "json-file"
options:
max-size: "10m" # Max size per file
max-file: "3" # Keep 3 files
```
## Networking
The bot connects outbound to:
- Discord API (discord.com)
- Database API (configured via `DB_URL`)
- Google Sheets API (sheets.googleapis.com)
No inbound ports are exposed (bot initiates all connections).
### Custom Network
The compose file creates a bridge network:
```yaml
networks:
major-domo-network:
driver: bridge
```
## Troubleshooting
### Bot Won't Start
1. **Check logs:**
```bash
docker-compose logs discord-bot
```
2. **Verify environment variables:**
```bash
docker-compose exec discord-bot env | grep BOT_TOKEN
```
3. **Check credentials file:**
```bash
docker-compose exec discord-bot ls -la /data/
```
### Permission Errors
If you see permission errors accessing `/data` or `/logs`:
```bash
# Fix data directory permissions
chmod -R 755 data/
chmod 444 data/major-domo-service-creds.json
# Fix logs directory permissions
chmod -R 755 logs/
```
### Database Connection Issues
Test database connectivity:
```bash
docker-compose exec discord-bot python -c "
import aiohttp
import asyncio
import os
async def test():
url = os.getenv('DB_URL')
token = os.getenv('API_TOKEN')
async with aiohttp.ClientSession() as session:
async with session.get(f'{url}/health',
headers={'Authorization': f'Bearer {token}'}) as resp:
print(f'Status: {resp.status}')
print(await resp.text())
asyncio.run(test())
"
```
### High Memory Usage
If the bot uses too much memory:
1. **Check current usage:**
```bash
docker stats major-domo-discord-bot-v2
```
2. **Increase memory limit:**
```yaml
# In docker-compose.yml
deploy:
resources:
limits:
memory: 1G # Increase from 512M
```
3. **Restart with new limits:**
```bash
docker-compose up -d
```
### Container Keeps Restarting
Check exit code and error:
```bash
docker-compose ps
docker logs major-domo-discord-bot-v2 --tail=50
```
Common issues:
- Invalid `BOT_TOKEN` - Check .env file
- Missing credentials - Check `/data` mount
- Database unreachable - Check `DB_URL`
## Production Deployment
### Best Practices
1. **Use specific image tags:**
```bash
docker tag major-domo/discord-bot-v2:latest major-domo/discord-bot-v2:v2.0.0
```
2. **Enable auto-restart:**
```yaml
restart: unless-stopped # Already set in compose file
```
3. **Set production environment:**
```bash
ENVIRONMENT=production
LOG_LEVEL=INFO
```
4. **Monitor resource usage:**
```bash
docker stats major-domo-discord-bot-v2
```
5. **Regular updates:**
```bash
git pull
docker-compose build --no-cache
docker-compose up -d
```
### Backup Strategy
Backup critical data:
```bash
# Backup logs
tar -czf logs-backup-$(date +%Y%m%d).tar.gz logs/
# Backup configuration
cp .env .env.backup
# Backup credentials
cp data/major-domo-service-creds.json data/creds.backup.json
```
## Updates and Maintenance
### Update Bot Code (Production)
```bash
# 1. Pull latest image from Docker Hub
docker-compose pull
# 2. Restart with new image
docker-compose up -d
# 3. Verify it's running
docker-compose logs -f discord-bot
```
### Update Bot Code (Development)
```bash
# 1. Pull latest code
git pull
# 2. Rebuild image
docker-compose -f docker-compose.dev.yml build
# 3. Restart with new image
docker-compose -f docker-compose.dev.yml up -d
# 4. Verify it's running
docker-compose -f docker-compose.dev.yml logs -f discord-bot
```
### Update Dependencies
```bash
# 1. Update requirements.txt locally
pip install -U discord.py pydantic aiohttp
pip freeze > requirements.txt
# 2. Rebuild image with new dependencies
docker-compose build --no-cache
# 3. Restart
docker-compose up -d
```
### Database Migration
If the database API is updated:
```bash
# 1. Update DB_URL in .env if needed
nano .env
# 2. Restart bot to pick up new configuration
docker-compose restart discord-bot
# 3. Test connectivity
docker-compose logs -f discord-bot
```
## File Comparison: Production vs Development
### `docker-compose.yml` (Production)
- Pulls pre-built image from Docker Hub: `manticorum67/major-domo-discordapp:latest`
- Environment: `production`
- Log level: `INFO` (default)
- Resource limits: 512MB RAM, 1 CPU
- No source code mounting
### `docker-compose.dev.yml` (Development)
- Builds image locally from Dockerfile
- Environment: `development`
- Log level: `DEBUG` (default)
- Resource limits: 1GB RAM, 2 CPU (more generous)
- Optional source code mounting for live updates
### When to Use Each
**Use Production (`docker-compose.yml`)**:
- Production servers
- Staging environments
- Any deployment not modifying code
- Faster deployment (no build step)
**Use Development (`docker-compose.dev.yml`)**:
- Local development
- Testing code changes
- Building new features
- Debugging issues
## Additional Resources
- **Discord.py Documentation**: https://discordpy.readthedocs.io/
- **Docker Best Practices**: https://docs.docker.com/develop/dev-best-practices/
- **Python 3.13 Release Notes**: https://docs.python.org/3.13/whatsnew/
## Support
For issues or questions:
1. Check logs: `docker-compose logs discord-bot`
2. Review bot documentation in `CLAUDE.md` and command READMEs
3. Check health status: `docker inspect major-domo-discord-bot-v2`