feat(phase-6): Complete testing and deployment setup

Testing:
- Add pytest configuration (pytest.ini)
- Add test fixtures (tests/conftest.py)
- Add ContentGenerator tests (13 tests)
- Add ContentScheduler tests (16 tests)
- Add PublisherManager tests (16 tests)
- All 45 tests passing

Production Docker:
- Add docker-compose.prod.yml with healthchecks, resource limits
- Add Dockerfile.prod with multi-stage build, non-root user
- Add nginx.prod.conf with SSL, rate limiting, security headers
- Add .env.prod.example template

Maintenance Scripts:
- Add backup.sh for database and media backups
- Add restore.sh for database restoration
- Add cleanup.sh for log rotation and Docker cleanup
- Add healthcheck.sh with Telegram alerts

Documentation:
- Add DEPLOY.md with complete deployment guide

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-28 02:12:34 +00:00
parent 354270be98
commit 85bda6abcf
15 changed files with 2296 additions and 0 deletions

240
docker-compose.prod.yml Normal file
View File

@@ -0,0 +1,240 @@
version: '3.8'
# ===========================================
# PRODUCCIÓN - Social Media Automation
# Uso: docker-compose -f docker-compose.prod.yml up -d
# ===========================================
services:
# ===========================================
# APLICACIÓN PRINCIPAL (FastAPI)
# ===========================================
app:
build:
context: .
dockerfile: Dockerfile.prod
container_name: social-automation-app
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
environment:
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
- REDIS_URL=redis://redis:6379/0
env_file:
- .env.prod
volumes:
- uploaded_images:/app/uploads
- logs:/app/logs
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
restart: always
networks:
- social-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.25'
memory: 256M
# ===========================================
# CELERY WORKER (Procesamiento de tareas)
# ===========================================
worker:
build:
context: .
dockerfile: Dockerfile.prod
container_name: social-automation-worker
command: celery -A app.worker.celery_app worker --loglevel=warning --concurrency=4
environment:
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
- REDIS_URL=redis://redis:6379/0
env_file:
- .env.prod
volumes:
- uploaded_images:/app/uploads
- logs:/app/logs
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
restart: always
networks:
- social-network
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
# ===========================================
# CELERY BEAT (Programador de tareas)
# ===========================================
beat:
build:
context: .
dockerfile: Dockerfile.prod
container_name: social-automation-beat
command: celery -A app.worker.celery_app beat --loglevel=warning
environment:
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
- REDIS_URL=redis://redis:6379/0
env_file:
- .env.prod
volumes:
- logs:/app/logs
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
restart: always
networks:
- social-network
deploy:
resources:
limits:
cpus: '0.25'
memory: 256M
# ===========================================
# FLOWER (Monitor de Celery) - Solo acceso interno
# ===========================================
flower:
build:
context: .
dockerfile: Dockerfile.prod
container_name: social-automation-flower
command: celery -A app.worker.celery_app flower --port=5555 --basic_auth=${FLOWER_USER}:${FLOWER_PASSWORD}
environment:
- REDIS_URL=redis://redis:6379/0
env_file:
- .env.prod
depends_on:
- redis
- worker
restart: always
networks:
- social-network
deploy:
resources:
limits:
cpus: '0.25'
memory: 256M
# ===========================================
# POSTGRESQL (Base de datos)
# ===========================================
db:
image: postgres:15-alpine
container_name: social-automation-db
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backups:/backups
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
restart: always
networks:
- social-network
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
# ===========================================
# REDIS (Cola de mensajes)
# ===========================================
redis:
image: redis:7-alpine
container_name: social-automation-redis
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
restart: always
networks:
- social-network
deploy:
resources:
limits:
cpus: '0.25'
memory: 256M
# ===========================================
# NGINX (Reverse Proxy + SSL)
# ===========================================
nginx:
image: nginx:alpine
container_name: social-automation-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.prod.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- ./dashboard/static:/usr/share/nginx/html/static:ro
- nginx_logs:/var/log/nginx
depends_on:
app:
condition: service_healthy
restart: always
networks:
- social-network
healthcheck:
test: ["CMD", "nginx", "-t"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
cpus: '0.25'
memory: 128M
# ===========================================
# VOLÚMENES
# ===========================================
volumes:
postgres_data:
driver: local
redis_data:
driver: local
uploaded_images:
driver: local
logs:
driver: local
nginx_logs:
driver: local
# ===========================================
# REDES
# ===========================================
networks:
social-network:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.28.0.0/16