================================== Docker Architecture & Deployment ================================== System Overview =============== This document describes the Docker container architecture for LUStores running on a VM host, including volume mappings, networking, and data persistence strategies. Architecture Diagram ==================== .. mermaid:: graph TB subgraph "Host VM" subgraph "Docker Network: lustores_network
172.20.0.0/16" subgraph "Web Layer" NGINX[nginx:alpine
:80, :443
SSL Termination] end subgraph "Application Layer" APP[LUStores App
st7ma784/lustores:latest
:5000] AUTH[Replit Auth
st7ma784/replitauth:latest
:3001] end subgraph "Data Layer" DB[(PostgreSQL 15
:5432
university_inventory)] REDIS[(Redis 7
:6379
Session Store)] end subgraph "Support Services" CERTBOT[Certbot
SSL Renewal] WATCHTOWER[Watchtower
Auto-updates] end end subgraph "Host Volumes" DBVOL[/db
PostgreSQL Data] REDISVOL[redis_data
Redis Data] LOGS[./logs
Application Logs] CERTBOT_CONF[./certbot/conf
SSL Certificates] CERTBOT_WWW[./certbot/www
ACME Challenge] NGINX_CONF[./nginx
Config Files] ENV[.env.prod
Environment Config] end end subgraph "External" INTERNET((Internet
Users)) DOCKERHUB((Docker Hub
Image Registry)) LETSENCRYPT((Let's Encrypt
Certificate Authority)) end INTERNET -->|HTTPS :443| NGINX INTERNET -->|HTTP :80| NGINX NGINX -->|proxy_pass| APP APP -->|health checks| NGINX APP --> DB APP --> REDIS APP --> AUTH CERTBOT -->|cert renewal| LETSENCRYPT CERTBOT --> CERTBOT_CONF CERTBOT --> CERTBOT_WWW NGINX --> CERTBOT_CONF NGINX --> NGINX_CONF NGINX --> LOGS DB --> DBVOL REDIS --> REDISVOL APP --> LOGS WATCHTOWER -->|monitors| APP WATCHTOWER -->|monitors| AUTH WATCHTOWER -->|pulls updates| DOCKERHUB Container Details ================= nginx - Reverse Proxy & SSL Termination ---------------------------------------- - **Image**: ``nginx:alpine`` - **Ports**: - ``80:80`` - HTTP (redirects to HTTPS) - ``443:443`` - HTTPS - **Volumes**: - ``./nginx/nginx.conf.template:/etc/nginx/templates/default.conf.template:ro`` - ``./certbot/conf:/etc/letsencrypt:ro`` - SSL certificates - ``./certbot/www:/var/www/certbot:ro`` - ACME challenges - ``./logs/nginx:/var/log/nginx`` - Access & error logs - **Health Check**: ``nc -z 127.0.0.1 80`` every 30s - **Restart Policy**: ``unless-stopped`` app - Main LUStores Application -------------------------------- - **Image**: ``st7ma784/lustores:latest`` - **Internal Port**: ``5000`` (not exposed externally) - **Environment**: - ``NODE_ENV=production`` - ``DATABASE_URL`` - PostgreSQL connection - ``SESSION_SECRET``, ``JWT_SECRET`` - Security keys - ``DOMAIN``, ``EMAIL`` - Deployment config - **Depends On**: ``db`` (healthy), ``replit-auth`` (healthy) - **Volumes**: ``./logs:/app/logs`` - Application logs - **Health Check**: ``wget --spider http://127.0.0.1:5000/health`` every 30s - **Restart Policy**: ``unless-stopped`` - **Labels**: ``com.centurylinklabs.watchtower.enable=true`` - Auto-update enabled db - PostgreSQL Database ------------------------- .. warning:: The database volume is mounted at ``/db`` on the host - this is CRITICAL for backups! - **Image**: ``postgres:15-alpine`` - **Port**: ``5432:5432`` - **Database**: ``university_inventory`` - **Volumes**: - ``/db:/var/lib/postgresql/data`` - **CRITICAL**: Host volume at ``/db`` - ``./init.sql:/docker-entrypoint-initdb.d/init.sql`` - Schema initialization - **Environment**: - ``POSTGRES_DB=university_inventory`` - ``POSTGRES_USER=postgres`` - ``POSTGRES_PASSWORD=${DB_PASSWORD}`` - ``PGDATA=/var/lib/postgresql/data/pgdata`` - **Health Check**: ``pg_isready -U postgres -d university_inventory`` every 10s - **Restart Policy**: ``unless-stopped`` redis - Session Store & Cache ------------------------------ - **Image**: ``redis:7-alpine`` - **Port**: ``6379:6379`` - **Volumes**: ``redis_data:/data`` - Named Docker volume - **Command**: ``redis-server --appendonly yes`` - AOF persistence enabled - **Restart Policy**: ``unless-stopped`` replit-auth - Authentication Service ------------------------------------- - **Image**: ``st7ma784/replitauth:latest`` - **Port**: ``3001:3001`` - **Environment**: - ``PORT=3001`` - ``JWT_SECRET=${JWT_SECRET}`` - ``ALLOWED_ORIGINS=https://${DOMAIN}`` - **Health Check**: ``wget --spider http://127.0.0.1:3001/health`` every 30s - **Restart Policy**: ``unless-stopped`` - **Labels**: Watchtower enabled with graceful shutdown (``SIGTERM``) certbot - SSL Certificate Management ------------------------------------- - **Image**: ``certbot/certbot`` - **Volumes**: - ``./certbot/conf:/etc/letsencrypt`` - Certificate storage - ``./certbot/www:/var/www/certbot`` - ACME challenge directory - ``./logs/certbot:/var/log/certbot`` - Renewal logs - **Environment**: - ``DOMAIN=${DOMAIN}`` - Your domain name - ``EMAIL=${EMAIL}`` - Admin email for notifications - ``CERTBOT_STAGING`` - Use staging server for testing - **Function**: Automatically renews certificates every 12 hours - **Restart Policy**: ``unless-stopped`` watchtower - Automatic Container Updates ----------------------------------------- - **Image**: ``containrrr/watchtower:latest`` - **Volumes**: ``/var/run/docker.sock:/var/run/docker.sock`` - Docker API access - **Environment**: - ``WATCHTOWER_CLEANUP=true`` - Remove old images - ``WATCHTOWER_SCHEDULE=0 */15 * * * *`` - Check every 15 minutes - ``WATCHTOWER_LABEL_ENABLE=true`` - Only update labeled containers - ``WATCHTOWER_NOTIFICATION_WEBHOOK_URL`` - Notifications to app - **Restart Policy**: ``unless-stopped`` - **Labels**: ``watchtower.enable=false`` - Don't update itself Network Configuration ====================== **Network**: ``lustores_network`` - **Driver**: ``bridge`` - **Subnet**: ``172.20.0.0/16`` - **Purpose**: Isolated internal communication between containers Service Discovery ----------------- Docker DNS automatically resolves container names: - ``http://app:5000`` - Application - ``http://replit-auth:3001`` - Auth service - ``postgresql://postgres:${DB_PASSWORD}@db:5432/university_inventory`` - Database Volume Strategy =============== Critical Data Volumes (MUST BACKUP) ------------------------------------ PostgreSQL Database - /db (Host Volume) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. danger:: This is the MOST important data to backup! - **Location**: ``/db`` on host VM - **Contains**: All application data, users, inventory, orders, sales - **Backup Strategy**: See :doc:`backup-restore` Redis Data - redis_data (Docker Volume) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - **Type**: Named Docker volume - **Contains**: Session data, cache - **Backup Priority**: Medium (transient data) - **Location**: Managed by Docker (typically ``/var/lib/docker/volumes/``) Configuration Files (MUST BACKUP) ---------------------------------- SSL Certificates - ./certbot/conf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - **Contains**: Let's Encrypt certificates and keys - **Backup Priority**: High - **Renewal**: Automatic via certbot, but backup recommended Environment Configuration - .env.prod ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. danger:: Store encrypted backup in secure location! - **Contains**: All secrets, passwords, configuration - **Backup Priority**: CRITICAL - **Security**: Never commit to git, store encrypted Nginx Configuration - ./nginx/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - **Contains**: Web server configuration - **Backup Priority**: Medium (can be recreated, but contains custom settings) Port Mapping ============ .. list-table:: Port Configuration :header-rows: 1 :widths: 20 15 15 15 35 * - Service - Internal - External - Protocol - Purpose * - nginx - 80 - 80 - HTTP - Redirect to HTTPS * - nginx - 443 - 443 - HTTPS - Main access point * - app - 5000 - (none) - HTTP - Internal only (via nginx) * - replit-auth - 3001 - 3001 - HTTP - Auth service * - db - 5432 - 5432 - PostgreSQL - Database (exposed for admin) * - redis - 6379 - 6379 - Redis - Cache (exposed for admin) .. note:: In production, consider closing external access to db:5432 and redis:6379 by removing port mappings from docker-compose.prod.yml Data Flow ========= .. mermaid:: sequenceDiagram participant User participant nginx participant app participant auth as replit-auth participant db as PostgreSQL participant redis as Redis User->>nginx: HTTPS Request :443 nginx->>nginx: Terminate SSL nginx->>app: HTTP Request :5000 app->>auth: Validate Token :3001 auth-->>app: Token Valid app->>db: Query Data :5432 db-->>app: Return Results app->>redis: Cache Session :6379 redis-->>app: Session Stored app-->>nginx: HTTP Response nginx-->>User: HTTPS Response Health Monitoring ================= All critical services have health checks: .. list-table:: Health Check Configuration :header-rows: 1 :widths: 15 30 10 10 10 15 * - Service - Check Command - Interval - Timeout - Retries - Start Period * - nginx - ``nc -z 127.0.0.1 80`` - 30s - 10s - 3 - 30s * - app - ``wget --spider .../health`` - 30s - 10s - 5 - 60s * - db - ``pg_isready -U postgres`` - 10s - 5s - 5 - 30s * - replit-auth - ``wget --spider .../health`` - 30s - 10s - 3 - 30s Monitoring Commands ------------------- Check health status:: docker compose -f docker-compose.prod.yml ps View health logs:: docker compose -f docker-compose.prod.yml logs -f app Automatic Updates (Watchtower) =============================== Watchtower monitors Docker Hub for new images and automatically updates: - **app** (``st7ma784/lustores:latest``) - **replit-auth** (``st7ma784/replitauth:latest``) Update Process -------------- 1. Watchtower checks Docker Hub every 15 minutes 2. If new image found, pulls the update 3. Stops old container gracefully 4. Starts new container 5. Removes old image 6. Sends webhook notification to app Manual Override --------------- Disable watchtower temporarily:: docker compose -f docker-compose.prod.yml stop watchtower Update specific service manually:: docker compose -f docker-compose.prod.yml pull app docker compose -f docker-compose.prod.yml up -d app Security Considerations ======================= 1. **SSL/TLS**: All external traffic encrypted via Let's Encrypt certificates 2. **Internal Network**: Containers communicate via isolated Docker network 3. **Secrets**: Managed via ``.env.prod`` file (not committed to git) 4. **Updates**: Automatic security updates via Watchtower 5. **Health Checks**: Automatic restart on failures 6. **Firewall**: Only ports 80 and 443 should be publicly accessible Troubleshooting =============== See :doc:`qrh` (Quick Reference Handbook) for common issues and solutions. Quick diagnostic commands:: # Check all container status docker compose -f docker-compose.prod.yml ps # View logs for specific service docker compose -f docker-compose.prod.yml logs -f app # Restart specific service docker compose -f docker-compose.prod.yml restart app # Check disk space df -h /db # Check Docker volumes docker volume ls docker volume inspect lustores_redis_data Related Documentation ===================== - :doc:`qrh` - Quick Reference Handbook for operators - :doc:`backup-restore` - Backup and restore procedures - :doc:`/deployment/production` - Production deployment guide - :doc:`/deployment/docker` - Docker setup guide