El agente ya funciona y tiene API. Pero vive en tu Mac: si lo apagas, muere. La Fase 5 lo saca al mundo: lo mete en un contenedor (Docker) y lo publica en Cloud Run, que le da una URL, lo enciende cuando alguien entra y lo apaga cuando nadie lo usa. Todo el despliegue real, con sus salidas, está dentro.
La frase más temida de la informática. Tu agente depende de una versión exacta de Python, de librerías, de tu
.venv… En otro ordenador, nada de eso está. Un contenedor resuelve esto: empaqueta el
sistema operativo mínimo + Python + librerías + tu código en una caja sellada que corre igual en
cualquier sitio. Ya lo hiciste con el RAG en el Art.2; esto es memoria muscular.
El Dockerfile es la receta para construir la imagen. Dos decisiones de diseño importan:
FROM python:3.13-slim # base mínima
COPY requirements.txt . # ① deps PRIMERO (capa cacheable)
RUN pip install -r requirements.txt
COPY herramientas.py agente.py api.py ./ # ② lista BLANCA
COPY datos_personales/cv_denys.md ./datos_personales/
COPY static/ ./static/
CMD ["sh","-c","uvicorn api:app --host 0.0.0.0 --port ${PORT:-8080}"]
agente.py, no reinstala las librerías (que no cambiaron) — reconstruye en segundos, no minutos..env exista en la
carpeta, no puede colarse en la imagen porque no está en la lista. Seguridad por construcción.--host 0.0.0.0 es obligatorio dentro de un contenedor: 127.0.0.1 solo se ve
a sí mismo. Y $PORT lo inyecta Cloud Run — no lo fijamos a mano.
Además de la lista blanca del Dockerfile, dos ficheros deciden qué sale de tu Mac:
| Fichero | Controla | Aquí sirve para |
|---|---|---|
.dockerignore | qué ve el constructor de Docker | que el .env ni entre al contexto de build |
.gcloudignore | qué sube gcloud a la nube | que suba el CV .md pero NO el .env ni el CV .html |
La trampa que ya te mordió en el Art.2:
Si NO existe .gcloudignore, gcloud usa tu .gitignore para decidir qué subir.
Y tu .gitignore esconde datos_personales/ (el CV) por privacidad. Resultado: subirías una imagen
sin CV → el agente arrancaría roto (no puede leer el CV para el match_cv). En el Art.2 fue
el corpus el que faltaba. Por eso el .gcloudignore de esta fase deja pasar cv_denys.md a propósito,
y bloquea todo lo sensible. Lo verificamos antes de subir (ver §06).
La API key de OpenAI y tu token de acceso son secretos. No van en el código, ni en git, ni en la imagen
Docker (que es pública dentro de tu proyecto). Van en Secret Manager de GCP, y Cloud Run los inyecta como
variables de entorno al arrancar. El código los lee con os.environ — le da igual si vienen de un .env
local o de la nube.
Creamos un secreto NUEVO para el agente (APP_TOKEN_AGENTE), separado del token del RAG: así puedes
revocar uno sin tocar el otro.
Cloud Run toma tu imagen y le da una URL pública con HTTPS. Su gracia: escala a cero. Si nadie usa el agente, no hay ninguna copia corriendo y no pagas nada. Cuando llega la primera petición, arranca un contenedor en ~1-2 s (el "arranque en frío") y sirve. Ideal para un demo de portfolio: coste ≈ 0 en reposo.
Lo primero: preguntar a gcloud qué ficheros subiría, y confirmar que el .env queda fuera y el CV
.md dentro. Salida real:
| Prueba | Resultado |
|---|---|
GET /salud | 200 {estado:ok, protegido:true} |
GET / (frontend) | 200 la página carga |
POST /preguntar sin token | 401 el agente ni se ejecuta |
POST /preguntar con token | 200 turnos:4 · pasos:[analizar,match,redactar] · completado:true |
El mismo bucle que probaste en la terminal, ahora corriendo en un contenedor en Europa, detrás de HTTPS y de tu token.
gpt-4o-mini — céntimos.
Pero por eso el token importa: sin él, cada visita de un bot te costaría 4 llamadas. El portero
(401) corta eso en seco: sin token válido, el agente ni arranca.| Concepto | Qué es aquí | Dónde vive fuera |
|---|---|---|
| Contenedor / Docker | la caja con el agente | estándar de despliegue en toda la industria |
| Imagen / capas | la receta del Dockerfile | cache de capas = builds rápidos en CI/CD |
| Build context | lo que sube .gcloudignore | controlar qué ve el constructor: seguridad y peso |
| Secret Manager | API key + token fuera del código | gestión de credenciales en cualquier cloud serio |
| Cloud Run / serverless | imagen → URL, escala a cero | AWS Lambda, Cloud Functions, Fargate… misma idea |
| Cold start | el arranque de la 1ª petición | compromiso clásico de lo serverless |
| HTTPS gestionado | el certificado de la URL | Cloud Run lo da gratis; en otros sitios es trabajo |
Para tu CV, en una frase: «Contenericé el agente con Docker y lo desplegué en Cloud Run con los secretos en Secret Manager y una lista blanca de ficheros verificada antes del build, sirviendo una demo pública protegida por token que escala a cero.» Eso es un flujo de despliegue completo, no un notebook.
El agente está vivo: dobe-agente…run.app.
Lo último es lucirlo: su página gemela en el portfolio, el enlace desde el roadmap, la tarjeta en
denysporynets.github.io, y subir el código publicable (sin el CV, sin el .env) a GitHub.