Docker Setup
Overview
Section titled “Overview”Documentación de la configuración Docker y Docker Compose para el ecosistema Nostromo.
Docker Compose Structure
Section titled “Docker Compose Structure”File: docker-compose.yml (ubicado en /opt/nostromo/)
version: "3.8"
services: mother: image: postgres:16-alpine container_name: nostromo_mother environment: POSTGRES_DB: nostromo POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data - ./init-scripts:/docker-entrypoint-initdb.d ports: - "5432:5432" restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] interval: 10s timeout: 5s retries: 5
orchestrator: build: context: ./orchestrator dockerfile: Dockerfile container_name: nostromo_orchestrator environment: NODE_ENV: production DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@mother:5432/nostromo JWT_SECRET: ${JWT_SECRET} depends_on: mother: condition: service_healthy ports: - "8000:8000" restart: unless-stopped volumes: - ./orchestrator/logs:/app/logs
etl: build: context: ./etl dockerfile: Dockerfile container_name: nostromo_etl environment: DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@mother:5432/nostromo depends_on: - mother restart: unless-stopped volumes: - ./etl/data:/app/data - ./etl/logs:/app/logs
volumes: postgres_data: driver: local
networks: default: name: nostromo_networkContainer Details
Section titled “Container Details”Mother (PostgreSQL)
Section titled “Mother (PostgreSQL)”Image: postgres:16-alpine
Exposed Port: 5432
Volumes:
postgres_data:/var/lib/postgresql/data- Persistent data./init-scripts:/docker-entrypoint-initdb.d- Init SQL scripts
Environment Variables:
POSTGRES_DB=nostromoPOSTGRES_USER=<SECRET>POSTGRES_PASSWORD=<SECRET>Health Check:
pg_isready -U postgresOrchestrator
Section titled “Orchestrator”Build Context: ./orchestrator/
Dockerfile:
FROM node:20-alpine
WORKDIR /app
# Install dependenciesCOPY package*.json ./RUN npm ci --only=production
# Copy sourceCOPY . .
# Build TypeScriptRUN npm run build
# Expose portEXPOSE 8000
# Start serverCMD ["node", "dist/server.js"]Exposed Port: 8000
Environment Variables:
NODE_ENV=productionDATABASE_URL=postgresql://user:pass@mother:5432/nostromoJWT_SECRET=<SECRET>JWT_EXPIRATION=24hPORT=8000ETL Service
Section titled “ETL Service”Build Context: ./etl/
Dockerfile:
FROM python:3.11-slim
WORKDIR /app
# Install system dependenciesRUN apt-get update && apt-get install -y \ postgresql-client \ && rm -rf /var/lib/apt/lists/*
# Install Python dependenciesCOPY requirements.txt ./RUN pip install --no-cache-dir -r requirements.txt
# Copy sourceCOPY . .
# Run cron jobs (if applicable)CMD ["python", "-m", "etl.scheduler"]Environment Variables:
DATABASE_URL=postgresql://user:pass@mother:5432/nostromoSII_SCRAPE_DELAY=2LOG_LEVEL=INFODocker Networks
Section titled “Docker Networks”Network Name: nostromo_network
Type: Bridge (default)
Inter-container Communication:
- Orchestrator → Mother via hostname
mother:5432 - ETL → Mother via hostname
mother:5432 - Containers se resuelven por nombre de servicio
Volumes
Section titled “Volumes”postgres_data
Section titled “postgres_data”Type: Named volume (managed by Docker)
Path: /var/lib/docker/volumes/nostromo_postgres_data/_data
Backup:
# Backup volumedocker run --rm -v nostromo_postgres_data:/data -v $(pwd):/backup \ alpine tar czf /backup/postgres_backup.tar.gz /data
# Restore volumedocker run --rm -v nostromo_postgres_data:/data -v $(pwd):/backup \ alpine tar xzf /backup/postgres_backup.tar.gz -C /Bind Mounts
Section titled “Bind Mounts”| Container | Host Path | Container Path | Purpose |
|---|---|---|---|
| Orchestrator | ./orchestrator/logs | /app/logs | Application logs |
| ETL | ./etl/logs | /app/logs | ETL logs |
| ETL | ./etl/data | /app/data | Scraped data cache |
| Mother | ./init-scripts | /docker-entrypoint-initdb.d | Init SQL |
Running Containers
Section titled “Running Containers”Start All Services
Section titled “Start All Services”cd /opt/nostromodocker-compose up -dExpected output:
Creating nostromo_mother ... doneCreating nostromo_orchestrator ... doneCreating nostromo_etl ... doneStop All Services
Section titled “Stop All Services”docker-compose downView Logs
Section titled “View Logs”# All containersdocker-compose logs -f
# Specific containerdocker-compose logs -f orchestratordocker-compose logs -f mother
# Last 100 linesdocker-compose logs --tail=100 orchestratorRebuild Container
Section titled “Rebuild Container”# Rebuild single servicedocker-compose build orchestrator
# Rebuild and restartdocker-compose up -d --build orchestratorEnvironment Variables
Section titled “Environment Variables”File: .env (located in /opt/nostromo/)
# PostgreSQLPOSTGRES_USER=nostromo_userPOSTGRES_PASSWORD=<STRONG_PASSWORD>
# JWTJWT_SECRET=<RANDOM_256_BIT_SECRET>JWT_EXPIRATION=24h
# Node.jsNODE_ENV=production
# ETLSII_SCRAPE_DELAY=2LOG_LEVEL=INFOContainer Health
Section titled “Container Health”Health Check Commands
Section titled “Health Check Commands”# Mother (PostgreSQL)docker exec nostromo_mother pg_isready -U nostromo_user
# Orchestratordocker exec nostromo_orchestrator curl -f http://localhost:8000/health
# View health statusdocker-compose psExpected output:
Name State Ports-----------------------------------------------nostromo_mother Up (healthy) 0.0.0.0:5432->5432/tcpnostromo_orchestrator Up 0.0.0.0:8000->8000/tcpnostromo_etl UpResource Limits
Section titled “Resource Limits”Recommended (añadir a docker-compose.yml):
services: mother: # ... existing config ... deploy: resources: limits: cpus: "2" memory: 2G reservations: cpus: "1" memory: 1G
orchestrator: deploy: resources: limits: cpus: "1" memory: 1GTroubleshooting
Section titled “Troubleshooting”Container won’t start
Section titled “Container won’t start”Symptoms: docker-compose ps shows Exited (1).
Debugging:
# View exit logsdocker-compose logs orchestrator
# Inspect containerdocker inspect nostromo_orchestrator
# Try interactive shelldocker run --rm -it \ --entrypoint /bin/sh \ nostromo_orchestratorCannot connect to Mother from Orchestrator
Section titled “Cannot connect to Mother from Orchestrator”Symptoms: Error: connect ECONNREFUSED mother:5432
Checks:
- Mother container running?
docker ps | grep mother - Health check passing?
docker inspect nostromo_mother | grep Health - Network exists?
docker network ls | grep nostromo
Fix:
# Restart Motherdocker-compose restart mother
# Verify networkdocker network inspect nostromo_networkDisk space full
Section titled “Disk space full”Symptoms: no space left on device
Cleanup:
# Remove unused imagesdocker image prune -a
# Remove unused volumesdocker volume prune
# Remove stopped containersdocker container prune
# Nuclear option (removes EVERYTHING unused)docker system prune -a --volumesProduction Best Practices
Section titled “Production Best Practices”- ✅ Use specific image tags (NOT
latest) - ✅ Set resource limits (CPU, memory)
- ✅ Use health checks for all services
- ✅ Enable logging drivers (e.g., json-file with rotation)
- ✅ Use secrets management (Docker Swarm secrets or Vault)
- ✅ Regularly update base images (security patches)
Monitoring
Section titled “Monitoring”Docker Stats
Section titled “Docker Stats”# Real-time container metricsdocker stats
# Expected output:# CONTAINER CPU % MEM USAGE / LIMIT NET I/O# nostromo_mother 5% 500MB / 2GB 1kB / 2kB# nostromo_orchestrator 10% 200MB / 1GB 50kB / 100kBGrafana + cAdvisor
Section titled “Grafana + cAdvisor”Setup (optional):
- cAdvisor: Container metrics exporter
- Prometheus: Scrape cAdvisor metrics
- Grafana: Visualize container health
Related Documentation
Section titled “Related Documentation”- Infrastructure: Networking - Network topology
- Infrastructure: PostgreSQL Config - Database tuning
- Runbook: Deploy - Deployment procedures
- ADR-002: Pool Management - Connection pooling
Changelog
Section titled “Changelog”| Fecha | Version | Cambios |
|---|---|---|
| 2026-01-18 | 1.0 | Documentación inicial creada |