Deploy de Django en AWS (ECS Fargate + ECR + ALB + CloudFront + EventBridge) — Guía paso a paso
Esta guía documenta el flujo de despliegue para un backend Django corriendo en AWS ECS Fargate, con imágenes en ECR, expuesto por un Application Load Balancer (ALB), y opcionalmente acelerado/protegido por CloudFront. Además, tareas programadas (como crawlers o jobs diarios) corren mediante EventBridge.
Arquitectura (qué está pasando)
- ECR (Elastic Container Registry): aquí se guardan las imágenes Docker versionadas (tags únicos).
- ECS Fargate: corre tu contenedor sin administrar servidores. Tu servicio mantiene 1+ tasks “vivas”.
- Task Definition (example-web): es la “receta” del contenedor (imagen, env vars, puertos, CPU/RAM, logs, etc.). Cada cambio crea una revisión nueva (ej: example-web:3).
- Service (example-backend-service-s2zz1bm3): mantiene la cantidad deseada de tasks y aplica despliegues (rolling deploy).
- ALB (Application Load Balancer): recibe tráfico HTTP/HTTPS y lo manda a tus tasks (Target Group → container:8000).
- CloudFront: puede ir delante del ALB para cache, TLS, WAF, y mejor latencia. (En logs verás requests a /admin y /static).
- CloudWatch Logs: logs del contenedor (entrypoint, gunicorn, etc.).
- EventBridge (Schedules): ejecuta tareas programadas (por ejemplo un crawler diario) disparando un task en ECS.
Los 3 comandos importantes del deploy
- Build + Push a ECR (tag único)
- Registrar nueva revisión de Task Definition (apuntando al nuevo tag)
- Actualizar el Service para usar la nueva revisión + force new deployment
0) Pre-requisitos
- Docker corriendo localmente
- AWS CLI configurado (profile:
example) - Repositorio con Dockerfile + entrypoint.sh funcional
- Permisos para: ECR push, ECS register task definition, ECS update-service
1) Build + Push con tag único (ECR)
Este paso empaqueta tu código en una imagen Docker, la etiqueta con un tag único (por ejemplo el commit corto), y la sube a ECR.
export AWS_REGION=us-east-2
export AWS_PROFILE=example
export AWS_ACCOUNT_ID=XXXXXXXX
export ECR_REPO=example-backend
export ECR_URI=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPO
export IMAGE_TAG=$(git rev-parse --short HEAD)
# Login a ECR
aws ecr get-login-password --region $AWS_REGION --profile $AWS_PROFILE \
| docker login --username AWS --password-stdin \
$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
# Build, tag y push
docker build -t $ECR_REPO:$IMAGE_TAG .
docker tag $ECR_REPO:$IMAGE_TAG $ECR_URI:$IMAGE_TAG
docker push $ECR_URI:$IMAGE_TAGResultado esperado: verás “Pushed” y un digest: sha256:....
2) Actualiza la Task Definition (example-web) para usar ese tag
Idea clave: aunque ya subiste la imagen a ECR, ECS NO la usa hasta que una Task Definition revision apunte a ese tag.
Opción A (recomendada): AWS Console
- Ve a ECS → Task definitions → example-web
- Click en Create new revision
- En Container: web cambia Image URI de:
...:latest
a:
030512689265.dkr.ecr.us-east-2.amazonaws.com/example-backend:$IMAGE_TAG
- Click Create
✅ Resultado: se crea una nueva revisión, por ejemplo example-web:4.
Opción B: CLI (equivalente, avanzado)
Este método descarga la task definition actual, reemplaza el campo image del contenedor web,
y registra una nueva revisión.
# Requiere jq
export AWS_REGION=us-east-2
export FAMILY=example-web
export NEW_IMAGE="030512689265.dkr.ecr.us-east-2.amazonaws.com/example-backend:$IMAGE_TAG"
# Toma la última definición y prepara JSON registrable
aws ecs describe-task-definition \
--task-definition $FAMILY \
--region $AWS_REGION \
| jq --arg IMG "$NEW_IMAGE" '
.taskDefinition
| del(.taskDefinitionArn,.revision,.status,.requiresAttributes,.compatibilities,.registeredAt,.registeredBy)
| .containerDefinitions |= map(if .name=="web" then .image=$IMG else . end)
' > td.json
# Registrar nueva revisión
aws ecs register-task-definition \
--cli-input-json file://td.json \
--region $AWS_REGION3) Update Service a la nueva revisión (deploy real)
Ahora le dices al Service que use la nueva revisión de task definition y haga rollout.
Opción A (AWS Console)
- ECS → Clusters → example-cluster
- Tab Services
- Click example-backend-service-s2zz1bm3
- Click Update
- En Task definition revision selecciona la nueva (ej:
example-web:4) - Marca ✅ Force new deployment
- Click Update service
Opción B (CLI equivalente)
aws ecs update-service \
--cluster example-cluster \
--service example-backend-service-s2zz1bm3 \
--task-definition example-web \
--force-new-deployment \
--region us-east-24) Confirmar que quedó (checks rápidos)
En AWS Console
- ECS → Clusters → example-cluster → Services
- Abre example-backend-service-s2zz1bm3
- En Deployments valida:
Task definition = example-web:<NUEVA_REVISION>
y que haya Running = Desired
Validación en CloudWatch Logs
- Busca que el log muestre algo como:
Collecting static...yxxx static files copied
- Y que no haya errores en el entrypoint (ej.
command not found)
Validación HTTP (lo que te confirma todo)
- /admin carga con estilos
- /static/… responde 200 (no 404)
- /healthz responde 200 (ALB health checks)
Notas prácticas
- Evita latest en producción: usa tags únicos (
git rev-parse --short HEADo timestamp). - Si subiste imagen pero no se reflejó: casi siempre es porque no creaste una nueva revisión de task definition apuntando a ese tag.
- Jobs diarios (EventBridge): se usan para correr tareas tipo crawler sin tocar el servicio web (ej: “run-task” programado).
- CloudFront: útil para TLS, WAF, caching y latencia; típicamente apunta al ALB como origen.
English

