swl-ses 3.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +425 -0
- package/_userland/agentes/.gitkeep +0 -0
- package/_userland/habilidades/.gitkeep +0 -0
- package/agentes/accesibilidad-wcag-swl.md +683 -0
- package/agentes/arquitecto-swl.md +210 -0
- package/agentes/auto-evolucion-swl.md +408 -0
- package/agentes/backend-api-swl.md +442 -0
- package/agentes/backend-node-swl.md +439 -0
- package/agentes/backend-python-swl.md +469 -0
- package/agentes/backend-workers-swl.md +444 -0
- package/agentes/cloud-infra-swl.md +466 -0
- package/agentes/consolidador-swl.md +487 -0
- package/agentes/datos-swl.md +568 -0
- package/agentes/depurador-swl.md +301 -0
- package/agentes/devops-ci-swl.md +352 -0
- package/agentes/disenador-ui-swl.md +546 -0
- package/agentes/documentador-swl.md +323 -0
- package/agentes/frontend-angular-swl.md +603 -0
- package/agentes/frontend-css-swl.md +700 -0
- package/agentes/frontend-react-swl.md +672 -0
- package/agentes/frontend-swl.md +483 -0
- package/agentes/frontend-tailwind-swl.md +808 -0
- package/agentes/implementador-swl.md +235 -0
- package/agentes/investigador-swl.md +274 -0
- package/agentes/investigador-ux-swl.md +482 -0
- package/agentes/migrador-swl.md +389 -0
- package/agentes/mobile-android-swl.md +473 -0
- package/agentes/mobile-cross-swl.md +501 -0
- package/agentes/mobile-ios-swl.md +464 -0
- package/agentes/notificador-swl.md +886 -0
- package/agentes/observabilidad-swl.md +408 -0
- package/agentes/orquestador-swl.md +490 -0
- package/agentes/planificador-swl.md +222 -0
- package/agentes/producto-prd-swl.md +565 -0
- package/agentes/release-manager-swl.md +545 -0
- package/agentes/rendimiento-swl.md +691 -0
- package/agentes/revisor-codigo-swl.md +254 -0
- package/agentes/revisor-seguridad-swl.md +316 -0
- package/agentes/tdd-qa-swl.md +323 -0
- package/agentes/ux-disenador-swl.md +498 -0
- package/bin/swl-ses.js +119 -0
- package/comandos/swl/actualizar.md +117 -0
- package/comandos/swl/aprender.md +348 -0
- package/comandos/swl/auditar-deps.md +390 -0
- package/comandos/swl/autoresearch.md +346 -0
- package/comandos/swl/checkpoint.md +296 -0
- package/comandos/swl/compactar.md +283 -0
- package/comandos/swl/crear-skill.md +609 -0
- package/comandos/swl/discutir-fase.md +230 -0
- package/comandos/swl/ejecutar-fase.md +302 -0
- package/comandos/swl/evolucionar.md +377 -0
- package/comandos/swl/instalar.md +220 -0
- package/comandos/swl/mapear-codebase.md +205 -0
- package/comandos/swl/nuevo-proyecto.md +154 -0
- package/comandos/swl/planear-fase.md +221 -0
- package/comandos/swl/release.md +405 -0
- package/comandos/swl/salud.md +382 -0
- package/comandos/swl/verificar.md +292 -0
- package/habilidades/accesibilidad-a11y/SKILL.md +584 -0
- package/habilidades/angular-avanzado/SKILL.md +491 -0
- package/habilidades/angular-moderno/SKILL.md +326 -0
- package/habilidades/api-rest-diseno/SKILL.md +302 -0
- package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
- package/habilidades/aprendizaje-continuo/SKILL.md +369 -0
- package/habilidades/async-python/SKILL.md +474 -0
- package/habilidades/auth-patrones/SKILL.md +488 -0
- package/habilidades/auto-evolucion-protocolo/SKILL.md +376 -0
- package/habilidades/autoresearch/SKILL.md +248 -0
- package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
- package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
- package/habilidades/checklist-calidad/SKILL.md +247 -0
- package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
- package/habilidades/checklist-seguridad/SKILL.md +224 -0
- package/habilidades/checkpoints-verificacion/SKILL.md +309 -0
- package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
- package/habilidades/ci-cd-pipelines/SKILL.md +583 -0
- package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
- package/habilidades/cloud-aws/SKILL.md +497 -0
- package/habilidades/compactacion-contexto/SKILL.md +201 -0
- package/habilidades/contenedores-docker/SKILL.md +453 -0
- package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
- package/habilidades/css-moderno/SKILL.md +463 -0
- package/habilidades/datos-etl/SKILL.md +486 -0
- package/habilidades/dependencias-auditoria/SKILL.md +293 -0
- package/habilidades/deprecacion-migracion/SKILL.md +485 -0
- package/habilidades/design-tokens/SKILL.md +519 -0
- package/habilidades/discutir-fase/SKILL.md +167 -0
- package/habilidades/diseno-responsivo/SKILL.md +326 -0
- package/habilidades/django-experto/SKILL.md +395 -0
- package/habilidades/doc-sync/SKILL.md +259 -0
- package/habilidades/ejecutar-fase/SKILL.md +199 -0
- package/habilidades/estructura-proyecto-claude/SKILL.md +459 -0
- package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +213 -0
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
- package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
- package/habilidades/event-driven/SKILL.md +580 -0
- package/habilidades/extractor-de-aprendizajes/SKILL.md +234 -0
- package/habilidades/fastapi-experto/SKILL.md +368 -0
- package/habilidades/frontend-avanzado/SKILL.md +555 -0
- package/habilidades/git-worktrees-paralelo/SKILL.md +246 -0
- package/habilidades/iam-secretos/SKILL.md +511 -0
- package/habilidades/instalar-sistema/SKILL.md +140 -0
- package/habilidades/kubernetes-orquestacion/SKILL.md +549 -0
- package/habilidades/manejo-errores/SKILL.md +512 -0
- package/habilidades/mapear-codebase/SKILL.md +199 -0
- package/habilidades/microservicios/SKILL.md +473 -0
- package/habilidades/mobile-flutter/SKILL.md +566 -0
- package/habilidades/mobile-react-native/SKILL.md +493 -0
- package/habilidades/monitoring-alertas/SKILL.md +447 -0
- package/habilidades/node-experto/SKILL.md +521 -0
- package/habilidades/notificaciones-multicanal/SKILL.md +448 -0
- package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
- package/habilidades/nuevo-proyecto/SKILL.md +183 -0
- package/habilidades/patrones-python/SKILL.md +381 -0
- package/habilidades/performance-baseline/SKILL.md +243 -0
- package/habilidades/planear-fase/SKILL.md +184 -0
- package/habilidades/postgresql-experto/SKILL.md +379 -0
- package/habilidades/react-experto/SKILL.md +434 -0
- package/habilidades/react-optimizacion/SKILL.md +328 -0
- package/habilidades/release-semver/SKILL.md +226 -0
- package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
- package/habilidades/sql-optimizacion/SKILL.md +314 -0
- package/habilidades/tailwind-experto/SKILL.md +412 -0
- package/habilidades/tdd-workflow/SKILL.md +267 -0
- package/habilidades/testing-python/SKILL.md +350 -0
- package/habilidades/threat-model-lite/SKILL.md +218 -0
- package/habilidades/typescript-avanzado/SKILL.md +454 -0
- package/habilidades/ux-diseno/SKILL.md +488 -0
- package/habilidades/validacion-ci-sistema/SKILL.md +543 -0
- package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
- package/habilidades/verificar-trabajo/SKILL.md +208 -0
- package/habilidades/wireframes-flujos/SKILL.md +396 -0
- package/habilidades/workflow-claude-code/SKILL.md +359 -0
- package/hooks/calidad-pre-commit.js +578 -0
- package/hooks/escaneo-secretos.js +302 -0
- package/hooks/extraccion-aprendizajes.js +550 -0
- package/hooks/linea-estado.js +249 -0
- package/hooks/monitor-contexto.js +230 -0
- package/hooks/proteccion-rutas.js +249 -0
- package/manifiestos/hooks-config.json +41 -0
- package/manifiestos/modulos.json +318 -0
- package/manifiestos/perfiles.json +189 -0
- package/package.json +45 -0
- package/plantillas/PROJECT.md +122 -0
- package/plantillas/REQUIREMENTS.md +132 -0
- package/plantillas/ROADMAP.md +143 -0
- package/plantillas/STATE.md +109 -0
- package/plantillas/research/ARCHITECTURE.md +220 -0
- package/plantillas/research/FEATURES.md +175 -0
- package/plantillas/research/PITFALLS.md +299 -0
- package/plantillas/research/STACK.md +233 -0
- package/plantillas/research/SUMMARY.md +165 -0
- package/plugin.json +144 -0
- package/reglas/accesibilidad.md +269 -0
- package/reglas/api-diseno.md +400 -0
- package/reglas/arquitectura.md +183 -0
- package/reglas/cloud-infra.md +247 -0
- package/reglas/docs.md +245 -0
- package/reglas/estilo-codigo.md +179 -0
- package/reglas/git-workflow.md +186 -0
- package/reglas/performance.md +195 -0
- package/reglas/pruebas.md +159 -0
- package/reglas/seguridad.md +151 -0
- package/reglas/skills-estandar.md +473 -0
- package/scripts/actualizar.js +51 -0
- package/scripts/desinstalar.js +86 -0
- package/scripts/doctor.js +222 -0
- package/scripts/inicializar.js +89 -0
- package/scripts/instalador.js +333 -0
- package/scripts/lib/detectar-runtime.js +177 -0
- package/scripts/lib/estado.js +112 -0
- package/scripts/lib/hooks-settings.js +283 -0
- package/scripts/lib/manifiestos.js +138 -0
- package/scripts/lib/seguridad.js +160 -0
- package/scripts/publicar.js +209 -0
- package/scripts/validar.js +120 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: contenedores-docker
|
|
3
|
+
description: Docker y containerización. Dockerfiles optimizados con multi-stage builds, docker-compose, volúmenes, networking, health checks, security scanning, build caching, distroless images. Anti-patrones comunes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Docker y Containerización — Producción
|
|
7
|
+
|
|
8
|
+
Docker en producción requiere imágenes seguras, pequeñas y reproducibles.
|
|
9
|
+
Este skill cubre desde Dockerfiles hasta orquestación con Compose.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Dockerfile Base — Python API
|
|
14
|
+
|
|
15
|
+
```dockerfile
|
|
16
|
+
# =====================================================================
|
|
17
|
+
# Etapa 1: Dependencias (caché eficiente)
|
|
18
|
+
# =====================================================================
|
|
19
|
+
FROM python:3.12-slim AS deps
|
|
20
|
+
|
|
21
|
+
# Instalar dependencias del sistema (solo las necesarias)
|
|
22
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
23
|
+
build-essential \
|
|
24
|
+
libpq-dev \
|
|
25
|
+
&& rm -rf /var/lib/apt/lists/* # SIEMPRE limpiar en misma capa
|
|
26
|
+
|
|
27
|
+
WORKDIR /app
|
|
28
|
+
|
|
29
|
+
# Copiar SOLO archivos de dependencias primero (mejor caché)
|
|
30
|
+
COPY pyproject.toml uv.lock* requirements*.txt ./
|
|
31
|
+
|
|
32
|
+
# pip sin caché ni warnings innecesarios
|
|
33
|
+
RUN pip install --no-cache-dir --upgrade pip && \
|
|
34
|
+
pip install --no-cache-dir -r requirements.txt
|
|
35
|
+
|
|
36
|
+
# =====================================================================
|
|
37
|
+
# Etapa 2: Build (compilar assets si los hay)
|
|
38
|
+
# =====================================================================
|
|
39
|
+
FROM deps AS builder
|
|
40
|
+
|
|
41
|
+
COPY . .
|
|
42
|
+
RUN python -m compileall -q /app # Precompilar .pyc
|
|
43
|
+
|
|
44
|
+
# =====================================================================
|
|
45
|
+
# Etapa 3: Producción (imagen final mínima)
|
|
46
|
+
# =====================================================================
|
|
47
|
+
FROM python:3.12-slim AS production
|
|
48
|
+
|
|
49
|
+
# Seguridad: NO correr como root
|
|
50
|
+
RUN groupadd --gid 1001 appuser && \
|
|
51
|
+
useradd --uid 1001 --gid appuser --shell /bin/bash --create-home appuser
|
|
52
|
+
|
|
53
|
+
WORKDIR /app
|
|
54
|
+
|
|
55
|
+
# Copiar solo lo necesario desde la etapa de build
|
|
56
|
+
COPY --from=builder --chown=appuser:appuser /usr/local/lib/python3.12/site-packages \
|
|
57
|
+
/usr/local/lib/python3.12/site-packages
|
|
58
|
+
COPY --from=builder --chown=appuser:appuser /app /app
|
|
59
|
+
|
|
60
|
+
# Instalar dependencias de sistema mínimas para runtime
|
|
61
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
62
|
+
libpq5 \
|
|
63
|
+
curl \
|
|
64
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
65
|
+
|
|
66
|
+
USER appuser
|
|
67
|
+
|
|
68
|
+
# Variables de entorno para Python en contenedor
|
|
69
|
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
70
|
+
PYTHONUNBUFFERED=1 \
|
|
71
|
+
PYTHONFAULTHANDLER=1 \
|
|
72
|
+
PORT=8000
|
|
73
|
+
|
|
74
|
+
EXPOSE 8000
|
|
75
|
+
|
|
76
|
+
# Health check integrado en la imagen
|
|
77
|
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
|
78
|
+
CMD curl -f http://localhost:8000/health || exit 1
|
|
79
|
+
|
|
80
|
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", \
|
|
81
|
+
"--workers", "2", "--log-level", "info"]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 2. Multi-stage Build — Node.js + Angular
|
|
87
|
+
|
|
88
|
+
```dockerfile
|
|
89
|
+
# Etapa 1: Dependencias npm (caché por package-lock.json)
|
|
90
|
+
FROM node:20-alpine AS npm-deps
|
|
91
|
+
WORKDIR /app
|
|
92
|
+
COPY package.json package-lock.json ./
|
|
93
|
+
RUN npm ci --only=production
|
|
94
|
+
|
|
95
|
+
# Etapa 2: Build Angular
|
|
96
|
+
FROM node:20-alpine AS angular-builder
|
|
97
|
+
WORKDIR /app
|
|
98
|
+
COPY package.json package-lock.json ./
|
|
99
|
+
RUN npm ci # Incluye devDependencies para build
|
|
100
|
+
COPY . .
|
|
101
|
+
RUN npm run build -- --configuration=production --output-path=dist
|
|
102
|
+
|
|
103
|
+
# Etapa 3: Nginx para servir el SPA
|
|
104
|
+
FROM nginx:1.25-alpine AS production
|
|
105
|
+
|
|
106
|
+
# Configuración de Nginx optimizada
|
|
107
|
+
COPY nginx.conf /etc/nginx/nginx.conf
|
|
108
|
+
COPY --from=angular-builder /app/dist /usr/share/nginx/html
|
|
109
|
+
|
|
110
|
+
# Usuario no-root para nginx
|
|
111
|
+
RUN chown -R nginx:nginx /usr/share/nginx/html && \
|
|
112
|
+
chown -R nginx:nginx /var/cache/nginx && \
|
|
113
|
+
touch /var/run/nginx.pid && \
|
|
114
|
+
chown nginx:nginx /var/run/nginx.pid
|
|
115
|
+
|
|
116
|
+
USER nginx
|
|
117
|
+
|
|
118
|
+
EXPOSE 80
|
|
119
|
+
|
|
120
|
+
HEALTHCHECK --interval=30s --timeout=5s \
|
|
121
|
+
CMD curl -f http://localhost/health || exit 1
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 3. .dockerignore — Crítico para el Contexto de Build
|
|
127
|
+
|
|
128
|
+
```dockerignore
|
|
129
|
+
# Control de versiones
|
|
130
|
+
.git
|
|
131
|
+
.gitignore
|
|
132
|
+
|
|
133
|
+
# Dependencias locales (nunca copiar node_modules o venv)
|
|
134
|
+
node_modules
|
|
135
|
+
__pycache__
|
|
136
|
+
*.pyc
|
|
137
|
+
*.pyo
|
|
138
|
+
.venv
|
|
139
|
+
venv
|
|
140
|
+
env
|
|
141
|
+
|
|
142
|
+
# Tests y documentación
|
|
143
|
+
tests/
|
|
144
|
+
docs/
|
|
145
|
+
*.md
|
|
146
|
+
!README.md
|
|
147
|
+
|
|
148
|
+
# Archivos de configuración de desarrollo
|
|
149
|
+
.env
|
|
150
|
+
.env.*
|
|
151
|
+
*.env
|
|
152
|
+
docker-compose.override.yml
|
|
153
|
+
.editorconfig
|
|
154
|
+
.eslintrc*
|
|
155
|
+
.prettierrc*
|
|
156
|
+
|
|
157
|
+
# IDE
|
|
158
|
+
.vscode
|
|
159
|
+
.idea
|
|
160
|
+
*.swp
|
|
161
|
+
|
|
162
|
+
# Build outputs locales
|
|
163
|
+
dist/
|
|
164
|
+
build/
|
|
165
|
+
.angular/
|
|
166
|
+
coverage/
|
|
167
|
+
.pytest_cache/
|
|
168
|
+
|
|
169
|
+
# CI/CD
|
|
170
|
+
.github/
|
|
171
|
+
.gitlab-ci.yml
|
|
172
|
+
Dockerfile*
|
|
173
|
+
docker-compose*.yml
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 4. docker-compose — Entorno de Desarrollo Completo
|
|
179
|
+
|
|
180
|
+
```yaml
|
|
181
|
+
# docker-compose.yml
|
|
182
|
+
version: '3.9'
|
|
183
|
+
|
|
184
|
+
services:
|
|
185
|
+
api:
|
|
186
|
+
build:
|
|
187
|
+
context: .
|
|
188
|
+
dockerfile: Dockerfile
|
|
189
|
+
target: deps # Etapa de desarrollo (no producción)
|
|
190
|
+
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
|
191
|
+
volumes:
|
|
192
|
+
- .:/app # Hot reload en desarrollo
|
|
193
|
+
- /app/.venv # Excluir venv del host
|
|
194
|
+
ports:
|
|
195
|
+
- "8000:8000"
|
|
196
|
+
environment:
|
|
197
|
+
- DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/appdb
|
|
198
|
+
- REDIS_URL=redis://redis:6379/0
|
|
199
|
+
- DEBUG=true
|
|
200
|
+
env_file:
|
|
201
|
+
- .env.local # Variables de entorno sensibles
|
|
202
|
+
depends_on:
|
|
203
|
+
db:
|
|
204
|
+
condition: service_healthy
|
|
205
|
+
redis:
|
|
206
|
+
condition: service_healthy
|
|
207
|
+
networks:
|
|
208
|
+
- app-network
|
|
209
|
+
restart: unless-stopped
|
|
210
|
+
|
|
211
|
+
db:
|
|
212
|
+
image: postgres:15-alpine
|
|
213
|
+
volumes:
|
|
214
|
+
- postgres_data:/var/lib/postgresql/data
|
|
215
|
+
- ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
|
216
|
+
environment:
|
|
217
|
+
POSTGRES_DB: appdb
|
|
218
|
+
POSTGRES_USER: postgres
|
|
219
|
+
POSTGRES_PASSWORD: postgres
|
|
220
|
+
ports:
|
|
221
|
+
- "5432:5432" # Solo exponer en desarrollo
|
|
222
|
+
healthcheck:
|
|
223
|
+
test: ["CMD-SHELL", "pg_isready -U postgres -d appdb"]
|
|
224
|
+
interval: 10s
|
|
225
|
+
timeout: 5s
|
|
226
|
+
retries: 5
|
|
227
|
+
start_period: 30s
|
|
228
|
+
networks:
|
|
229
|
+
- app-network
|
|
230
|
+
|
|
231
|
+
redis:
|
|
232
|
+
image: redis:7-alpine
|
|
233
|
+
command: redis-server --appendonly yes --requirepass "${REDIS_PASSWORD:-dev_password}"
|
|
234
|
+
volumes:
|
|
235
|
+
- redis_data:/data
|
|
236
|
+
ports:
|
|
237
|
+
- "6379:6379"
|
|
238
|
+
healthcheck:
|
|
239
|
+
test: ["CMD", "redis-cli", "ping"]
|
|
240
|
+
interval: 10s
|
|
241
|
+
timeout: 3s
|
|
242
|
+
retries: 3
|
|
243
|
+
networks:
|
|
244
|
+
- app-network
|
|
245
|
+
|
|
246
|
+
nginx:
|
|
247
|
+
image: nginx:1.25-alpine
|
|
248
|
+
volumes:
|
|
249
|
+
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
|
250
|
+
- ./nginx/ssl:/etc/nginx/ssl:ro
|
|
251
|
+
ports:
|
|
252
|
+
- "80:80"
|
|
253
|
+
- "443:443"
|
|
254
|
+
depends_on:
|
|
255
|
+
- api
|
|
256
|
+
networks:
|
|
257
|
+
- app-network
|
|
258
|
+
|
|
259
|
+
volumes:
|
|
260
|
+
postgres_data:
|
|
261
|
+
driver: local
|
|
262
|
+
redis_data:
|
|
263
|
+
driver: local
|
|
264
|
+
|
|
265
|
+
networks:
|
|
266
|
+
app-network:
|
|
267
|
+
driver: bridge
|
|
268
|
+
ipam:
|
|
269
|
+
config:
|
|
270
|
+
- subnet: 172.20.0.0/16
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 5. Networking en Docker
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
# Crear red personalizada (mejores nombres DNS internos)
|
|
279
|
+
docker network create --driver bridge --subnet 172.21.0.0/16 mi-red
|
|
280
|
+
|
|
281
|
+
# Inspeccionar red
|
|
282
|
+
docker network inspect mi-red
|
|
283
|
+
|
|
284
|
+
# Contenedores en la misma red se comunican por nombre
|
|
285
|
+
# api puede conectarse a "db" por nombre → postgresql://db:5432/appdb
|
|
286
|
+
|
|
287
|
+
# MAL: usar --link (obsoleto)
|
|
288
|
+
docker run --link db:database api
|
|
289
|
+
|
|
290
|
+
# BIEN: red compartida
|
|
291
|
+
docker run --network mi-red --name api mi-imagen-api
|
|
292
|
+
docker run --network mi-red --name db postgres:15
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## 6. Volúmenes — Persistencia Correcta
|
|
298
|
+
|
|
299
|
+
```yaml
|
|
300
|
+
# Tipos de volúmenes y cuándo usar cada uno
|
|
301
|
+
|
|
302
|
+
# 1. Named volumes (RECOMENDADO para datos de BD)
|
|
303
|
+
volumes:
|
|
304
|
+
postgres_data: # Docker administra la ubicación
|
|
305
|
+
|
|
306
|
+
# 2. Bind mounts (SOLO para desarrollo — hot reload)
|
|
307
|
+
volumes:
|
|
308
|
+
- ./src:/app/src # Código fuente del host → contenedor
|
|
309
|
+
|
|
310
|
+
# 3. tmpfs (datos efímeros — sesiones, caché temporal)
|
|
311
|
+
tmpfs:
|
|
312
|
+
- /tmp
|
|
313
|
+
- /run
|
|
314
|
+
|
|
315
|
+
# MAL: montar directorio completo en producción
|
|
316
|
+
volumes:
|
|
317
|
+
- .:/app # ¡Incluye .git, node_modules, .env!
|
|
318
|
+
|
|
319
|
+
# BIEN: montar solo lo necesario
|
|
320
|
+
volumes:
|
|
321
|
+
- ./config:/app/config:ro # :ro = solo lectura
|
|
322
|
+
- ./logs:/app/logs # Solo el directorio de logs
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## 7. Variables de Entorno y Secrets
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
# MAL: secrets en variables de entorno del Dockerfile
|
|
331
|
+
ENV DATABASE_PASSWORD=supersecreta123
|
|
332
|
+
|
|
333
|
+
# MAL: pasar secrets en build args (aparecen en capas)
|
|
334
|
+
docker build --build-arg DB_PASS=secreto .
|
|
335
|
+
|
|
336
|
+
# BIEN: runtime environment variables (nunca en imagen)
|
|
337
|
+
docker run -e DATABASE_URL="postgresql://..." mi-imagen
|
|
338
|
+
|
|
339
|
+
# BIEN: Docker Secrets (en Swarm)
|
|
340
|
+
docker secret create db_password ./db_password.txt
|
|
341
|
+
|
|
342
|
+
# BIEN: En docker-compose con .env (nunca commitar .env real)
|
|
343
|
+
# .env.example (sí commitear)
|
|
344
|
+
DATABASE_URL=postgresql://usuario:password@localhost:5432/db
|
|
345
|
+
SECRET_KEY=cambiar-en-produccion
|
|
346
|
+
|
|
347
|
+
# docker-compose.yml
|
|
348
|
+
env_file:
|
|
349
|
+
- .env
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## 8. Security Scanning — Pipeline de CI
|
|
355
|
+
|
|
356
|
+
```yaml
|
|
357
|
+
# .github/workflows/security.yml
|
|
358
|
+
name: Security Scan
|
|
359
|
+
|
|
360
|
+
on: [push, pull_request]
|
|
361
|
+
|
|
362
|
+
jobs:
|
|
363
|
+
scan:
|
|
364
|
+
runs-on: ubuntu-latest
|
|
365
|
+
steps:
|
|
366
|
+
- uses: actions/checkout@v4
|
|
367
|
+
|
|
368
|
+
- name: Build imagen
|
|
369
|
+
run: docker build -t mi-app:${{ github.sha }} .
|
|
370
|
+
|
|
371
|
+
# Trivy — escaneo de vulnerabilidades en imagen
|
|
372
|
+
- name: Trivy scan
|
|
373
|
+
uses: aquasecurity/trivy-action@master
|
|
374
|
+
with:
|
|
375
|
+
image-ref: mi-app:${{ github.sha }}
|
|
376
|
+
format: 'sarif'
|
|
377
|
+
output: 'trivy-results.sarif'
|
|
378
|
+
severity: 'CRITICAL,HIGH'
|
|
379
|
+
exit-code: '1' # Fallar el pipeline si hay vulns críticas
|
|
380
|
+
|
|
381
|
+
# Hadolint — linter de Dockerfile
|
|
382
|
+
- name: Hadolint
|
|
383
|
+
uses: hadolint/hadolint-action@v3.1.0
|
|
384
|
+
with:
|
|
385
|
+
dockerfile: Dockerfile
|
|
386
|
+
|
|
387
|
+
# Dockle — mejores prácticas de imagen
|
|
388
|
+
- name: Dockle
|
|
389
|
+
run: |
|
|
390
|
+
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
|
|
391
|
+
goodwithtech/dockle:latest --exit-code 1 mi-app:${{ github.sha }}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## 9. Optimización de Build Cache
|
|
397
|
+
|
|
398
|
+
```dockerfile
|
|
399
|
+
# ORDEN CRÍTICO para maximizar caché:
|
|
400
|
+
# 1. Lo que cambia MENOS al inicio
|
|
401
|
+
# 2. Lo que cambia MÁS al final
|
|
402
|
+
|
|
403
|
+
# MAL: copiar todo antes de instalar dependencias
|
|
404
|
+
COPY . .
|
|
405
|
+
RUN pip install -r requirements.txt # Invalida caché con CUALQUIER cambio
|
|
406
|
+
|
|
407
|
+
# BIEN: dependencias antes que código
|
|
408
|
+
COPY requirements.txt .
|
|
409
|
+
RUN pip install -r requirements.txt # Se cachea hasta que requirements.txt cambie
|
|
410
|
+
COPY . . # Aquí va el código que cambia frecuentemente
|
|
411
|
+
|
|
412
|
+
# BuildKit — caché de montaje (pip, npm, apt)
|
|
413
|
+
# syntax=docker/dockerfile:1
|
|
414
|
+
FROM python:3.12-slim
|
|
415
|
+
|
|
416
|
+
RUN --mount=type=cache,target=/root/.cache/pip \
|
|
417
|
+
pip install -r requirements.txt
|
|
418
|
+
|
|
419
|
+
RUN --mount=type=cache,target=/var/cache/apt \
|
|
420
|
+
apt-get update && apt-get install -y libpq-dev
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## 10. Anti-patrones Comunes
|
|
426
|
+
|
|
427
|
+
| Anti-patrón | Consecuencia | Corrección |
|
|
428
|
+
|-------------|-------------|------------|
|
|
429
|
+
| `FROM python:3.12` (imagen completa) | Imagen 1GB+ innecesaria | `python:3.12-slim` o `distroless` |
|
|
430
|
+
| Correr como `root` en contenedor | Escalación de privilegios | `USER 1001` en Dockerfile |
|
|
431
|
+
| `COPY . .` antes de dependencias | Invalidar caché en cada cambio | Copiar deps primero |
|
|
432
|
+
| Sin `.dockerignore` | Contexto enorme, secretos incluidos | `.dockerignore` siempre |
|
|
433
|
+
| `apt-get` sin `rm -rf /var/lib/apt/lists/*` | Imagen más grande | Limpiar en misma `RUN` |
|
|
434
|
+
| Secrets en `ARG` o `ENV` | Visibles en `docker history` | Runtime env o secrets |
|
|
435
|
+
| Latest tag en producción | No reproducible, puede romper | Tag de versión exacta |
|
|
436
|
+
| Sin `HEALTHCHECK` | Orquestador no sabe si está sano | `HEALTHCHECK` siempre |
|
|
437
|
+
| `CMD` como shell string | Signals no llegan al proceso | `CMD ["ejecutable", "arg"]` forma exec |
|
|
438
|
+
| Múltiples procesos en un contenedor | Viola principio de responsabilidad única | Un proceso por contenedor |
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
## 11. Checklist de Imagen Productiva
|
|
443
|
+
|
|
444
|
+
- [ ] Multi-stage build — imagen final < 200MB si posible
|
|
445
|
+
- [ ] Usuario no-root definido
|
|
446
|
+
- [ ] Variables sensibles fuera de la imagen
|
|
447
|
+
- [ ] `HEALTHCHECK` definido
|
|
448
|
+
- [ ] `.dockerignore` presente y completo
|
|
449
|
+
- [ ] Dependencias del sistema limpiadas en misma capa de RUN
|
|
450
|
+
- [ ] Tag de versión semántica (no `latest`) en producción
|
|
451
|
+
- [ ] Escaneo de vulnerabilidades en CI/CD
|
|
452
|
+
- [ ] `CMD` en forma exec (array), no shell
|
|
453
|
+
- [ ] `PYTHONUNBUFFERED=1` y `PYTHONDONTWRITEBYTECODE=1` para Python
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
2
|
+
# Dockerfile multi-stage para aplicaciones Python (FastAPI / Django)
|
|
3
|
+
# Optimizado para producción: imagen pequeña, sin root, sin caché innecesario.
|
|
4
|
+
#
|
|
5
|
+
# USO:
|
|
6
|
+
# docker build -t mi-app:1.0.0 .
|
|
7
|
+
# docker build --target deps -t mi-app:deps . # solo la etapa de dependencias
|
|
8
|
+
#
|
|
9
|
+
# VARIABLES DE BUILD (--build-arg):
|
|
10
|
+
# PYTHON_VERSION Versión de Python (default: 3.12)
|
|
11
|
+
# APP_PORT Puerto expuesto (default: 8000)
|
|
12
|
+
# APP_USER_UID UID del usuario sin privilegios (default: 1001)
|
|
13
|
+
#
|
|
14
|
+
# INSTRUCCIÓN: Reemplazar todos los valores entre [corchetes] con los reales.
|
|
15
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
16
|
+
|
|
17
|
+
ARG PYTHON_VERSION=3.12
|
|
18
|
+
ARG APP_PORT=8000
|
|
19
|
+
ARG APP_USER_UID=1001
|
|
20
|
+
|
|
21
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
# Etapa 1: deps — instalar dependencias Python (máximo cache hit en rebuilds)
|
|
23
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
FROM python:${PYTHON_VERSION}-slim AS deps
|
|
25
|
+
|
|
26
|
+
# Dependencias del sistema mínimas (solo las necesarias para compilar wheels)
|
|
27
|
+
# INSTRUCCIÓN: ajustar según las librerías Python que uses
|
|
28
|
+
# psycopg2 → libpq-dev
|
|
29
|
+
# Pillow → libjpeg-dev zlib1g-dev
|
|
30
|
+
# lxml → libxml2-dev libxslt-dev
|
|
31
|
+
# cryptography → libssl-dev
|
|
32
|
+
RUN apt-get update \
|
|
33
|
+
&& apt-get install -y --no-install-recommends \
|
|
34
|
+
build-essential \
|
|
35
|
+
libpq-dev \
|
|
36
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
37
|
+
|
|
38
|
+
WORKDIR /app
|
|
39
|
+
|
|
40
|
+
# Copiar SOLO los archivos de dependencias primero.
|
|
41
|
+
# Esto permite que Docker reutilice la capa de pip install si el código cambia
|
|
42
|
+
# pero las dependencias no cambian.
|
|
43
|
+
COPY pyproject.toml uv.lock* requirements*.txt ./
|
|
44
|
+
|
|
45
|
+
# Actualizar pip e instalar dependencias sin caché
|
|
46
|
+
RUN pip install --no-cache-dir --upgrade pip==24.* \
|
|
47
|
+
&& pip install --no-cache-dir -r requirements.txt
|
|
48
|
+
|
|
49
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
50
|
+
# Etapa 2: builder — copiar código y precompilar bytecode
|
|
51
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
52
|
+
FROM deps AS builder
|
|
53
|
+
|
|
54
|
+
# Copiar el código fuente DESPUÉS de instalar dependencias (mejor cache hit)
|
|
55
|
+
COPY . .
|
|
56
|
+
|
|
57
|
+
# Precompilar .pyc — reduce el tiempo de arranque del contenedor en producción
|
|
58
|
+
# -q suprime output, -b escribe .pyc junto a los .py
|
|
59
|
+
RUN python -m compileall -q /app
|
|
60
|
+
|
|
61
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
62
|
+
# Etapa 3: production — imagen final mínima sin herramientas de build
|
|
63
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
64
|
+
FROM python:${PYTHON_VERSION}-slim AS production
|
|
65
|
+
|
|
66
|
+
ARG APP_PORT
|
|
67
|
+
ARG APP_USER_UID
|
|
68
|
+
|
|
69
|
+
# Instalar SOLO dependencias de runtime (sin herramientas de compilación)
|
|
70
|
+
# INSTRUCCIÓN: ajustar según las librerías que uses en runtime
|
|
71
|
+
RUN apt-get update \
|
|
72
|
+
&& apt-get install -y --no-install-recommends \
|
|
73
|
+
libpq5 \
|
|
74
|
+
curl \
|
|
75
|
+
&& rm -rf /var/lib/apt/lists/* \
|
|
76
|
+
&& apt-get clean
|
|
77
|
+
|
|
78
|
+
# ── Seguridad: usuario sin privilegios ────────────────────────────────────────
|
|
79
|
+
# NUNCA correr como root en producción
|
|
80
|
+
RUN groupadd --gid ${APP_USER_UID} appuser \
|
|
81
|
+
&& useradd \
|
|
82
|
+
--uid ${APP_USER_UID} \
|
|
83
|
+
--gid ${APP_USER_UID} \
|
|
84
|
+
--no-create-home \
|
|
85
|
+
--shell /sbin/nologin \
|
|
86
|
+
appuser
|
|
87
|
+
|
|
88
|
+
WORKDIR /app
|
|
89
|
+
|
|
90
|
+
# Copiar dependencias instaladas y código compilado desde las etapas anteriores
|
|
91
|
+
COPY --from=builder /usr/local/lib/python*/site-packages /usr/local/lib/python3.12/site-packages/
|
|
92
|
+
COPY --from=builder /usr/local/bin /usr/local/bin/
|
|
93
|
+
COPY --from=builder /app /app
|
|
94
|
+
|
|
95
|
+
# Establecer permisos correctos ANTES de cambiar de usuario
|
|
96
|
+
RUN chown -R appuser:appuser /app
|
|
97
|
+
|
|
98
|
+
# Cambiar al usuario sin privilegios
|
|
99
|
+
USER appuser
|
|
100
|
+
|
|
101
|
+
# ── Variables de entorno de runtime ───────────────────────────────────────────
|
|
102
|
+
# INSTRUCCIÓN: estas son las variables mínimas recomendadas para Python en producción
|
|
103
|
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
104
|
+
PYTHONUNBUFFERED=1 \
|
|
105
|
+
PYTHONFAULTHANDLER=1 \
|
|
106
|
+
PYTHONHASHSEED=random \
|
|
107
|
+
# FastAPI/Uvicorn
|
|
108
|
+
PORT=${APP_PORT} \
|
|
109
|
+
# INSTRUCCIÓN: agregar variables de entorno propias de la aplicación
|
|
110
|
+
# Las variables con valores sensibles deben venir de secrets, NO hardcodeadas aquí
|
|
111
|
+
APP_ENV=production
|
|
112
|
+
|
|
113
|
+
EXPOSE ${APP_PORT}
|
|
114
|
+
|
|
115
|
+
# ── Health check ──────────────────────────────────────────────────────────────
|
|
116
|
+
# INSTRUCCIÓN: reemplazar /health con el endpoint real de health check
|
|
117
|
+
# interval: frecuencia del check
|
|
118
|
+
# timeout: tiempo máximo de respuesta
|
|
119
|
+
# start_period: tiempo antes del primer check (para que la app arranque)
|
|
120
|
+
# retries: intentos fallidos antes de marcar como unhealthy
|
|
121
|
+
HEALTHCHECK \
|
|
122
|
+
--interval=30s \
|
|
123
|
+
--timeout=10s \
|
|
124
|
+
--start-period=15s \
|
|
125
|
+
--retries=3 \
|
|
126
|
+
CMD curl -f http://localhost:${APP_PORT}/health || exit 1
|
|
127
|
+
|
|
128
|
+
# ── Comando de inicio ─────────────────────────────────────────────────────────
|
|
129
|
+
# INSTRUCCIÓN: ajustar según el framework que uses
|
|
130
|
+
#
|
|
131
|
+
# FastAPI con Uvicorn:
|
|
132
|
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
|
|
133
|
+
#
|
|
134
|
+
# FastAPI con Gunicorn + Uvicorn workers (para producción con múltiples CPUs):
|
|
135
|
+
# CMD ["gunicorn", "app.main:app", "--workers", "4", "--worker-class", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000"]
|
|
136
|
+
#
|
|
137
|
+
# Django con Gunicorn:
|
|
138
|
+
# CMD ["gunicorn", "[nombre_proyecto].wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "4"]
|
|
139
|
+
|
|
140
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
141
|
+
# .dockerignore recomendado (crear en la raíz del proyecto):
|
|
142
|
+
# ───────────────────────────────────────────────────────────────────────────────
|
|
143
|
+
# __pycache__/
|
|
144
|
+
# *.pyc
|
|
145
|
+
# *.pyo
|
|
146
|
+
# .pytest_cache/
|
|
147
|
+
# .mypy_cache/
|
|
148
|
+
# .ruff_cache/
|
|
149
|
+
# .git/
|
|
150
|
+
# .gitignore
|
|
151
|
+
# .env
|
|
152
|
+
# .env.*
|
|
153
|
+
# !.env.example
|
|
154
|
+
# tests/
|
|
155
|
+
# docs/
|
|
156
|
+
# *.md
|
|
157
|
+
# docker-compose*.yml
|
|
158
|
+
# Dockerfile*
|
|
159
|
+
# .github/
|
|
160
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|