Día 68 - Documentación que Realmente Se Usa
🎯 Objetivo del Día
Crear documentación útil, simple y que el equipo realmente consulte
📋 Plan de Documentación Práctica
⏰ Tiempo | 📋 Tarea | 🎯 Resultado |
---|---|---|
30 min | 📝 README súper claro | Documentación que funciona |
40 min | 🚀 Guías de despliegue simples | Deploy sin errores |
35 min | 🔧 Manual de problemas comunes | Soluciones rápidas |
30 min | 📊 Dashboard de documentación | Todo en un lugar |
15 min | ✅ Validar con el equipo | Confirmar que sirve |
📝 Paso 1: README Súper Claro (30 min)
1.1 Template de README efectivo
# 🚀 DevOps Challenge Project
> Sistema de monitoreo y despliegue automatizado
## ⚡ Inicio Rápido (5 minutos)
### Prerrequisitos
- Docker y Docker Compose
- Git
- 4GB RAM libre
### Instalación
```bash
# 1. Clonar proyecto
git clone https://github.com/tu-usuario/devops-challenge.git
cd devops-challenge
# 2. Configurar entorno
cp .env.example .env
# Editar .env con tus valores
# 3. Levantar todo
docker-compose up -d
# 4. Verificar que funciona
curl http://localhost:3000
✅ Ya está funcionando! Ve a http://localhost:3000
📋 ¿Qué hace este proyecto?
- 🔍 Monitoreo: Grafana + Prometheus para métricas
- 🚨 Alertas: Notificaciones automáticas a Slack
- 🚀 CI/CD: Deploy automático con GitHub Actions
- 🛡️ Seguridad: Escaneo de vulnerabilidades automático
- 📊 Reportes: Dashboards y reportes diarios
🏗️ Arquitectura Simple
Internet → Load Balancer → App Servers → Database
↓
Monitoring Stack
(Grafana + Prometheus)
🚀 Comandos Útiles
Desarrollo
# Ver logs en tiempo real
docker-compose logs -f
# Reiniciar un servicio
docker-compose restart app
# Ejecutar tests
make test
# Ver métricas
curl http://localhost:9090/metrics
Producción
# Deploy a producción
make deploy-prod
# Ver estado de servicios
make status
# Backup de datos
make backup
# Rollback si algo falla
make rollback
🆘 Problemas Comunes
Problema | Solución |
---|---|
Port 3000 occupied | docker-compose down && docker-compose up -d |
Database connection error | docker-compose restart db |
High memory usage | docker system prune -f |
Grafana not loading | Check docker-compose logs grafana |
📚 Recursos Adicionales
- 🏗️ Arquitectura: Ver el sistema completo en el dashboard generado
- 🚀 Deploy: Scripts incluidos en este día para deploy automatizado
- 🔧 Troubleshooting: Base de conocimiento generada automáticamente
- 📊 Monitoreo: Dashboard HTML con todas las métricas
- 🛡️ Seguridad: Guías integradas en la documentación auto-generada
💡 ¿Algo no funciona? Revisa los logs con docker-compose logs -f
o el dashboard HTML generado
### 1.2 Script para generar documentación automática
```python
#!/usr/bin/env python3
# generate-docs.py - Generar documentación automáticamente
import os
import json
import subprocess
from datetime import datetime
from pathlib import Path
class DocumentationGenerator:
def __init__(self):
self.project_root = Path(".")
self.docs_dir = Path("docs")
self.docs_dir.mkdir(exist_ok=True)
def generate_project_overview(self):
"""Generar overview del proyecto"""
overview = {
"name": self.get_project_name(),
"description": self.get_project_description(),
"version": self.get_project_version(),
"services": self.get_docker_services(),
"ports": self.get_exposed_ports(),
"dependencies": self.get_dependencies()
}
with open(self.docs_dir / "project-overview.json", "w") as f:
json.dump(overview, f, indent=2)
return overview
def get_project_name(self):
"""Obtener nombre del proyecto"""
if Path("package.json").exists():
try:
with open("package.json") as f:
return json.load(f).get("name", "devops-project")
except:
pass
return Path.cwd().name
def get_project_description(self):
"""Obtener descripción del proyecto"""
if Path("package.json").exists():
try:
with open("package.json") as f:
return json.load(f).get("description", "DevOps Challenge Project")
except:
pass
return "Sistema de monitoreo y despliegue automatizado"
def get_project_version(self):
"""Obtener versión del proyecto"""
try:
result = subprocess.run(["git", "describe", "--tags", "--abbrev=0"],
capture_output=True, text=True)
if result.returncode == 0:
return result.stdout.strip()
except:
pass
return "1.0.0"
def get_docker_services(self):
"""Obtener servicios de Docker Compose"""
if not Path("docker-compose.yml").exists():
return []
try:
result = subprocess.run(["docker-compose", "config", "--services"],
capture_output=True, text=True)
if result.returncode == 0:
return result.stdout.strip().split('\n')
except:
pass
return []
def get_exposed_ports(self):
"""Obtener puertos expuestos"""
ports = []
if Path("docker-compose.yml").exists():
try:
with open("docker-compose.yml") as f:
content = f.read()
# Buscar patrones de puertos (simplificado)
import re
port_matches = re.findall(r'"(\d+):\d+"', content)
ports.extend(port_matches)
except:
pass
return list(set(ports))
def get_dependencies(self):
"""Obtener dependencias del proyecto"""
deps = {}
# Node.js dependencies
if Path("package.json").exists():
try:
with open("package.json") as f:
data = json.load(f)
deps["node"] = list(data.get("dependencies", {}).keys())[:10]
except:
pass
# Python dependencies
if Path("requirements.txt").exists():
try:
with open("requirements.txt") as f:
deps["python"] = [line.strip().split('==')[0]
for line in f if line.strip() and not line.startswith('#')][:10]
except:
pass
return deps
def generate_api_docs(self):
"""Generar documentación de API si existe"""
api_docs = {
"endpoints": [],
"authentication": "Bearer token",
"base_url": "http://localhost:3000/api"
}
# Buscar definiciones de rutas (muy simplificado)
api_files = list(Path(".").glob("**/*api*")) + list(Path(".").glob("**/*route*"))
for file_path in api_files[:5]: # Limitar a 5 archivos
if file_path.suffix in ['.js', '.py', '.ts']:
try:
with open(file_path) as f:
content = f.read()
# Buscar patrones básicos de endpoints
import re
endpoints = re.findall(r'@app\.route\(["\']([^"\']+)["\']', content)
endpoints += re.findall(r'app\.(get|post|put|delete)\(["\']([^"\']+)["\']', content)
for endpoint in endpoints:
if isinstance(endpoint, tuple):
method, path = endpoint
api_docs["endpoints"].append({"method": method.upper(), "path": path})
else:
api_docs["endpoints"].append({"method": "GET", "path": endpoint})
except:
continue
if api_docs["endpoints"]:
with open(self.docs_dir / "api-reference.json", "w") as f:
json.dump(api_docs, f, indent=2)
return api_docs
def generate_deployment_guide(self):
"""Generar guía de despliegue"""
deployment_guide = "# Guía de Despliegue\n\n"
deployment_guide += "## Despliegue Local\n"
deployment_guide += "1. git clone <repository-url>\n"
deployment_guide += "2. docker-compose up -d\n"
deployment_guide += "3. curl http://localhost:3000/health\n\n"
deployment_guide += "## Despliegue en Producción\n"
deployment_guide += "1. Conectar SSH a servidor\n"
deployment_guide += "2. Instalar Docker y Docker Compose\n"
deployment_guide += "3. Clonar repo y configurar .env\n"
deployment_guide += "4. docker-compose -f docker-compose.prod.yml up -d\n"
with open(self.docs_dir / "deployment.md", "w") as f:
f.write(deployment_guide)
return deployment_guide
def generate_troubleshooting_guide(self):
"""Generar guía de troubleshooting"""
troubleshooting = "# Guía de Troubleshooting\n\n"
troubleshooting += "## Docker Issues\n"
troubleshooting += "- Container no inicia: docker-compose logs [service]\n"
troubleshooting += "- Puerto ocupado: netstat -tulpn | grep :3000\n"
troubleshooting += "- Sin espacio: docker system prune -f\n\n"
troubleshooting += "## Database Issues\n"
troubleshooting += "- Connection refused: docker-compose restart db\n"
troubleshooting += "- Queries lentas: verificar indices\n\n"
troubleshooting += "## Application Issues\n"
troubleshooting += "- App no responde: verificar logs y recursos\n"
troubleshooting += "- Memory leaks: reiniciar containers\n"
with open(self.docs_dir / "troubleshooting.md", "w") as f:
f.write(troubleshooting)
return troubleshooting
with open(self.docs_dir / "troubleshooting.md", "w") as f:
f.write(troubleshooting)
return troubleshooting
def generate_docs_dashboard(self):
"""Generar dashboard HTML para documentación"""
overview = self.generate_project_overview()
# Crear HTML simple para dashboard
html_content = f"""
<h1>Documentation Dashboard</h1>
<p>Project: {overview['name']}</p>
<p>Version: {overview['version']}</p>
<div>Services: {len(overview['services'])} containers</div>
"""
with open(self.docs_dir / "index.html", "w") as f:
f.write(f"""
<!DOCTYPE html>
<html>
<head><title>Documentation</title></head>
<body>{html_content}</body>
</html>
""")
return "index.html"
def generate_all_docs(self):
"""Generar toda la documentación"""
print("📚 GENERANDO DOCUMENTACIÓN COMPLETA")
print("=" * 40)
# Generar cada sección
print("📊 Generando overview del proyecto...")
overview = self.generate_project_overview()
print("🔌 Generando documentación de API...")
api_docs = self.generate_api_docs()
print("🚀 Generando guía de despliegue...")
deployment = self.generate_deployment_guide()
print("🔧 Generando guía de troubleshooting...")
troubleshooting = self.generate_troubleshooting_guide()
print("📊 Generando dashboard de documentación...")
dashboard = self.generate_docs_dashboard()
print(f"\n✅ Documentación generada en: {self.docs_dir.absolute()}")
print(f"🌐 Abrir dashboard: file://{self.docs_dir.absolute()}/index.html")
return {
"overview": overview,
"api_docs": api_docs,
"deployment_guide": "deployment.md",
"troubleshooting_guide": "troubleshooting.md",
"dashboard": dashboard
}
if __name__ == "__main__":
generator = DocumentationGenerator()
result = generator.generate_all_docs()
print("\n📋 ARCHIVOS GENERADOS:")
for doc_type, filename in result.items():
if isinstance(filename, str):
print(f" • {doc_type}: {filename}")
else:
print(f" • {doc_type}: datos generados")
🚀 Paso 2: Guías de Despliegue Simples (40 min)
2.1 Ejecutar generador de documentación
# Crear y ejecutar generador
python3 generate-docs.py
# Ver documentación generada
ls -la docs/
# Abrir dashboard en navegador
open docs/index.html # macOS
# xdg-open docs/index.html # Linux
2.2 Guía de deploy de 1 comando
#!/bin/bash
# deploy.sh - Deploy en 1 comando
echo "🚀 DEPLOYING APPLICATION..."
echo "========================="
# Verificar prerrequisitos
if ! command -v docker >/dev/null 2>&1; then
echo "❌ Docker no está instalado"
exit 1
fi
if ! command -v docker-compose >/dev/null 2>&1; then
echo "❌ Docker Compose no está instalado"
exit 1
fi
# Configurar entorno si no existe
if [ ! -f ".env" ]; then
echo "📝 Creando .env desde template..."
cp .env.example .env
echo "⚠️ Edita .env antes de continuar"
echo "💡 Presiona Enter cuando esté listo..."
read -r
fi
# Build y deploy
echo "🔨 Building containers..."
docker-compose build
echo "🚀 Starting services..."
docker-compose up -d
echo "⏳ Esperando que servicios inicien..."
sleep 30
echo "🔍 Verificando servicios..."
docker-compose ps
echo "🌐 Testing endpoints..."
if curl -s http://localhost:3000/health > /dev/null; then
echo "✅ App principal: OK"
else
echo "❌ App principal: FAIL"
fi
if curl -s http://localhost:9090 > /dev/null; then
echo "✅ Prometheus: OK"
else
echo "❌ Prometheus: FAIL"
fi
if curl -s http://localhost:3001 > /dev/null; then
echo "✅ Grafana: OK"
else
echo "❌ Grafana: FAIL"
fi
echo
echo "🎉 Deploy completado!"
echo "📊 Dashboard: http://localhost:3001"
echo "📈 Métricas: http://localhost:9090"
echo "🚀 App: http://localhost:3000"
echo
echo "💡 Ver logs: docker-compose logs -f"
echo "🔧 Troubleshooting: cat docs/troubleshooting.md"
🔧 Paso 3: Manual de Problemas Comunes (35 min)
3.1 Base de conocimiento automática
#!/usr/bin/env python3
# knowledge-base.py - Base de conocimiento de problemas
import json
import re
from datetime import datetime
from pathlib import Path
class KnowledgeBase:
def __init__(self):
self.kb_file = Path("knowledge-base.json")
self.problems = self.load_knowledge_base()
def load_knowledge_base(self):
"""Cargar base de conocimiento básica"""
return {
"docker": {
"container_fails": ["Check logs: docker-compose logs", "Restart: docker-compose restart"],
"port_occupied": ["Find process: netstat -tulpn | grep :3000", "Kill process or change port"]
},
"application": {
"db_connection": ["Check DB status: docker-compose ps", "Restart DB: docker-compose restart db"],
"high_memory": ["Check usage: docker stats", "Restart containers"]
}
}
def search_problems(self, query):
"""Buscar problemas por query simple"""
results = []
query_lower = query.lower()
for category, problems in self.problems.items():
for problem, solutions in problems.items():
if query_lower in problem:
results.append({"problem": problem, "solutions": solutions})
return results
def generate_troubleshooting_guide(self):
"""Generar guía simple"""
guide = "# Troubleshooting Guide\n\n"
for category, problems in self.problems.items():
guide += f"## {category.title()}\n"
for problem, solutions in problems.items():
guide += f"- {problem}: {solutions[0]}\n"
guide += "\n"
return guide
if not user_input:
print("❌ Por favor describe el problema")
return
matches = self.search_problems(user_input)
if not matches:
print("🤔 No encontré problemas similares en la base de datos")
print("💡 Intenta con otros términos como:")
print(" • 'container not starting'")
print(" • 'connection refused'")
print(" • 'out of memory'")
print(" • 'high cpu usage'")
return
print(f"\n🎯 Encontré {len(matches)} posible(s) solución(es):")
print("-" * 40)
for i, match in enumerate(matches, 1):
problem_data = match["data"]
severity_emoji = "🔴" if problem_data["severity"] == "high" else "🟡" if problem_data["severity"] == "medium" else "🟢"
print(f"\n{i}. {severity_emoji} {match['problem_id'].replace('_', ' ').title()}")
print(f" 📂 Categoría: {match['category']}")
print(f" 🎯 Coincidencia: {match['match_text']}")
print(" 🔧 Soluciones:")
for j, solution in enumerate(problem_data["solutions"], 1):
print(f" {j}. {solution}")
print(f"\n💾 Guía completa disponible en: docs/troubleshooting-auto.md")
if __name__ == "__main__":
kb = KnowledgeBase()
# Generar guía automática
kb.generate_troubleshooting_guide()
print("✅ Guía de troubleshooting generada")
# Modo interactivo
print("\n" + "="*50)
kb.interactive_troubleshooting()
📊 Paso 4: Dashboard de Documentación (30 min)
4.1 Ejecutar todos los generadores
# Generar toda la documentación
echo "📚 Generando documentación completa..."
# 1. Documentación general
python3 generate-docs.py
# 2. Base de conocimiento
python3 knowledge-base.py
# 3. Verificar archivos generados
echo "📁 Archivos generados:"
ls -la docs/
# 4. Abrir dashboard
if command -v open >/dev/null 2>&1; then
open docs/index.html
elif command -v xdg-open >/dev/null 2>&1; then
xdg-open docs/index.html
else
echo "💡 Abre docs/index.html en tu navegador"
fi
echo "✅ Dashboard de documentación listo!"
✅ Paso 5: Validar con el Equipo (15 min)
5.1 Checklist de validación
#!/bin/bash
# validate-docs.sh - Validar que la documentación sirve
echo "📚 VALIDANDO DOCUMENTACIÓN"
echo "========================="
validation_errors=0
# 1. Verificar archivos principales
echo "📁 Verificando archivos de documentación..."
required_files=(
"README.md"
"docs/index.html"
"docs/deployment.md"
"docs/troubleshooting.md"
"docs/troubleshooting-auto.md"
"docs/project-overview.json"
"knowledge-base.json"
)
for file in "${required_files[@]}"; do
if [ -f "$file" ]; then
echo " ✅ $file"
else
echo " ❌ $file (faltante)"
((validation_errors++))
fi
done
# 2. Verificar que README tenga contenido esencial
echo "📝 Verificando contenido del README..."
if grep -q "Inicio Rápido" README.md; then
echo " ✅ Sección Inicio Rápido"
else
echo " ❌ Falta sección Inicio Rápido"
((validation_errors++))
fi
if grep -q "docker-compose up" README.md; then
echo " ✅ Comandos Docker"
else
echo " ❌ Faltan comandos Docker"
((validation_errors++))
fi
if grep -q "Problemas Comunes" README.md; then
echo " ✅ Sección Problemas Comunes"
else
echo " ❌ Falta sección Problemas Comunes"
((validation_errors++))
fi
# 3. Verificar que dashboard HTML funcione
echo "🌐 Verificando dashboard HTML..."
if grep -q "Documentation" docs/index.html; then
echo " ✅ Dashboard tiene título correcto"
else
echo " ❌ Dashboard mal formateado"
((validation_errors++))
fi
# 4. Verificar scripts de documentación
echo "🐍 Verificando scripts de documentación..."
if python3 -c "import generate-docs; print('OK')" 2>/dev/null; then
echo " ✅ generate-docs.py ejecutable"
else
echo " ❌ generate-docs.py tiene errores"
((validation_errors++))
fi
if python3 -c "import knowledge-base; print('OK')" 2>/dev/null; then
echo " ✅ knowledge-base.py ejecutable"
else
echo " ❌ knowledge-base.py tiene errores"
((validation_errors++))
fi
# 5. Test de troubleshooting interactivo
echo "🔧 Testing troubleshooting interactivo..."
if echo "container not starting" | python3 knowledge-base.py > /dev/null 2>&1; then
echo " ✅ Troubleshooting interactivo funciona"
else
echo " ❌ Troubleshooting interactivo falla"
((validation_errors++))
fi
# Resumen
echo
echo "📊 RESUMEN DE VALIDACIÓN:"
echo "========================"
if [ "$validation_errors" -eq 0 ]; then
echo "🎉 ¡TODA LA DOCUMENTACIÓN ESTÁ LISTA!"
echo "✅ El equipo puede usar la documentación sin problemas"
echo
echo "🔗 Links importantes:"
echo " • Dashboard: file://$(pwd)/docs/index.html"
echo " • Troubleshooting: python3 knowledge-base.py"
echo " • Deploy: bash deploy.sh"
else
echo "⚠️ $validation_errors problemas encontrados"
echo "📋 Corrige los errores antes de compartir con el equipo"
fi
echo
echo "💡 PRÓXIMOS PASOS:"
echo " 1. Comparte dashboard con el equipo"
echo " 2. Entrena al equipo en troubleshooting interactivo"
echo " 3. Actualiza docs regularmente: python3 generate-docs.py"
echo " 4. Recopila feedback y mejora la documentación"
# Generar checklist para el equipo
cat << 'EOF' > team-documentation-checklist.md
# 📚 Checklist de Documentación para el Equipo
## Para Nuevos Desarrolladores
- [ ] Leer README.md completo
- [ ] Ejecutar `bash deploy.sh` para setup inicial
- [ ] Verificar que todos los servicios funcionan
- [ ] Probar troubleshooting interactivo: `python3 knowledge-base.py`
- [ ] Bookmarkear dashboard: `docs/index.html`
## Para Uso Diario
- [ ] Usar `docs/troubleshooting.md` para problemas comunes
- [ ] Actualizar knowledge base con nuevos problemas encontrados
- [ ] Ejecutar `python3 generate-docs.py` después de cambios importantes
## Para DevOps/SRE
- [ ] Revisar métricas en dashboard
- [ ] Mantener guías de deploy actualizadas
- [ ] Agregar nuevos problemas a knowledge-base.py
- [ ] Validar documentación mensualmente: `bash validate-docs.sh`
## Feedback
- 📝 Problemas con docs: crear issue con tag 'documentation'
- 💡 Mejoras: sugerir en #devops-team
- 🔧 Nuevos problemas: ejecutar troubleshooting y agregar solución
EOF
echo "📋 Checklist para equipo creado: team-documentation-checklist.md"
🎯 Resultado Final
✅ Documentación que Realmente Se Usa:
📝 README Súper Claro - Setup en 5 minutos garantizado
🚀 Guías de Deploy - Un comando y funciona
🔧 Troubleshooting Inteligente - Base de conocimiento interactiva
📊 Dashboard Unificado - Todo en un lugar accesible
✅ Validación Completa - Confirmación que el equipo lo puede usar
🚀 Tu Equipo Ahora Tiene:
- Onboarding de 15 minutos en lugar de días
- Troubleshooting automático que resuelve problemas comunes
- Deploy confiable que funciona siempre
- Documentación viva que se actualiza automáticamente
- Dashboard centralizado con toda la información
💡 Mantener la Documentación
# Actualizar después de cambios
python3 generate-docs.py
# Agregar nuevos problemas
python3 knowledge-base.py
# Validar que todo funciona
bash validate-docs.sh
📚 ¡Tu equipo ahora tiene documentación que realmente usan porque es útil y fácil!
La mejor documentación es la que resuelve problemas reales del día a día. 📖✨