Bienvenida

La narrativa del taller

Una sola historia a lo largo de cuatro semanas:

CodeCommit → CodeBuild → ECR → ECS → CloudWatch

Servicios utilizados durante el curso

ServicioRol en el pipeline
CodeCommitRepositorio de código fuente
CodeBuildConstrucción de la imagen
ECRRegistro de imágenes Docker
CloudFormationInfraestructura como código
ECS + FargateEjecución de contenedores

Semana 1

El mecanismo de recuperación

Desde el primer día se practica destruir y recrear el ambiente completo.

Si algo sale mal, borramos el stack de CloudFormation, esperamos a que termine, y lo volvemos a lanzar con los mismos parámetros. El costo de un error se reduce a minutos de espera.

¿Cómo utilizar esta guía?

  1. Teoría — el problema del día y el servicio de AWS que lo resuelve.
  2. Práctica guiada — seguir los pasos numerados; intentar antes de ver la solución.
  3. Solución oculta — pulsar Ver solución si se producen bloqueos.
  4. Preguntas puente — conectan el miércoles (presencial) con el viernes (remota).

Requisitos previos

  • Cuenta AWS con permisos para CodeCommit, CodeBuild, ECR, CloudFormation, ECS/Fargate y DynamoDB.
  • Navegador actualizado (Chrome o Firefox).
  • Template taller-semana1.yaml, provisto por el instructor.

Objetivos de la sesión

  1. Crear el repositorio, clonarlo desde su origen y subir el código a CodeCommit
  2. Construir la imagen con CodeBuild
  3. Publicar la imagen en ECR
  4. Desplegar el template de CloudFormation para el despliegue inicial

Cada ejercicio incluye su solución oculta — botón Ver solución en la guía.

¿Qué es DevOps?

Una combinación de prácticas culturales, servicios y herramientas que aumentan la capacidad de entregar software a alta velocidad.

El objetivo es unificar las áreas de desarrollo y operaciones, las cuales comúnmente suelen estar completamente separadas, para conseguir un mejor flujo desde el código a la aplicación desplegada.

Contrato de Despliegue

%%{init: {"flowchart": {"defaultRenderer": "elk", "nodeSpacing": 30, "rankSpacing": 40, "padding": 8}, "themeVariables": {"clusterBkg": "#fffbeb", "clusterBorder": "#d97706"}}}%%
flowchart TD
    DCORE["Desarrollo · Núcleo<br/>Código · lógica de negocio · pruebas"]
    DSHELL["Desarrollo · Interfaz exterior<br/>Empaquetado · requisitos · instrumentación"]
    DCORE <--> DSHELL

    OCORE["Operaciones · Núcleo<br/>Infraestructura · seguridad · observabilidad · día 2"]
    OSHELL["Operaciones · Interfaz exterior<br/>Plataforma · políticas · capacidad · retroalimentación"]
    OCORE <--> OSHELL

    subgraph CONTRACT["Contrato de despliegue · interfaz compartida"]
        direction TB
        ART["Artefacto desplegable"]
        CFG["Configuración<br/>Argumentos · variables · secretos"]
        DEP["Dependencias<br/>Entorno de ejecución · bibliotecas · servicios"]
        EXP["Exposición<br/>Protocolos · puertos · cifrado · chequeos de salud"]

        ART ~~~ DEP
        CFG ~~~ EXP
    end

    DSHELL <-->|"Definición conjunta"| CONTRACT
    OSHELL <-->|"Validación operativa"| CONTRACT

    CONTRACT --> PIPELINE["Pipeline CI/CD"]
    PIPELINE --> PROD["Aplicación en producción"]

    DSHELL <-.-|"Retroalimentación de producción"| PROD
    OSHELL <-.-|"Métricas · logs · incidentes"| PROD

    classDef core fill:#dbeafe,stroke:#2563eb,color:#172554;
    classDef shell fill:#e0e7ff,stroke:#4f46e5,color:#1e1b4b;
    classDef contract fill:#fef3c7,stroke:#d97706,color:#451a03;
    classDef runtime fill:#dcfce7,stroke:#16a34a,color:#052e16;

    class DCORE,OCORE core;
    class DSHELL,OSHELL shell;
    class ART,CFG,DEP,EXP contract;
    class PIPELINE,PROD runtime;

    linkStyle 2,3 stroke:none;
    linkStyle 8,9 stroke-dasharray:5 4;

Pipeline de entrega continua (CI/CD)

Busca automatizar el flujo desde los últimos cambios realizados a la aplicación hasta su despliegue en producción, asegurando que cumple con los requisitos básicos de calidad, así como con el contexto necesario para su monitoreo continuo en día 2.

+-------------------------+     +-------------------+
|           CI            |     |        CD         |
| Código -> Build -> Test | --> | Deploy -> Monitor |
|          Day 1          |     |       Day 2       |
+-------------------------+     +-------------------+

Pre-requisitos

1. Instalar git

Obtener el cliente:

Verificar la instalación:

git --version

2. Configuración mínima

git config --global user.name "Su Nombre"
git config --global user.email su-correo@ejemplo.com

Existent múltiples formas de acceder a CodeCommit en AWS, las cuales dependen del tipo de autenticación que usen.

Por favor, utilicen aquella que se adapta a su usuario.

  1. Cuenta con usuario IAM: Acceso HTTPS o SSH
  2. Cuenta con SSO y IAM Identity Center: git-remote-codecommit

CodeCommit: repositorios Git administrados en AWS

AWS CodeCommit es un servicio de control de versiones compatible con Git, alojado completamente en AWS. No requiere instalar ni operar ningún servidor: se crea el repositorio desde la consola, y AWS se encarga de la disponibilidad, la seguridad, y los respaldos.

En este taller cada participante trabaja sobre su propio repositorio individual. Eso evita conflictos entre participantes y permite avanzar a ritmo propio. El nombre del repositorio sigue la convención taller-aws-<su-nombre>, donde <su-nombre> es el primer nombre en minúsculas y sin acentos (por ejemplo: taller-aws-maria).

Capacidades de la consola de CodeCommit

1. Code

Permite explorar los archivos y las carpetas de una rama, abrir su contenido y copiar la URL para clonar el repositorio.

2. Pull requests

Permite proponer la fusión de una rama en otra, revisar los cambios y registrar la discusión antes de integrar el trabajo.

3. Commits

Muestra el historial de cambios de la rama seleccionada. Cada commit identifica quién hizo el cambio, cuándo lo realizó y qué archivos modificó.

4. Branches

Lista las líneas de desarrollo del repositorio y permite crear una rama a partir de otra, por ejemplo dev desde main.

5. Git tags

Permite identificar un commit con un nombre estable, como v1.0.0, para señalar una versión, una entrega o un punto importante del historial.

6. Settings

Centraliza la configuración del repositorio, como los disparadores (triggers), las reglas de aprobación y las notificaciones. Las opciones disponibles dependen de los permisos de IAM.

GitOps

Del cambio al despliegue controlado

  1. Branches definen dónde se integra y prueba el código.
  2. PRs hacen visible la revisión y la aprobación.
  3. Tags identifican una versión concreta que se puede desplegar.
  4. Eventos conectan los cambios con los pipelines y los controles operativos.

Flujos de Aprobación

gitGraph
    commit id: "base"
    branch dev
    checkout dev
    commit id: "D1"
    branch feature-work
    checkout feature-work
    commit id: "F1"
    commit id: "F2"
    checkout dev
    merge feature-work id: "PR #42"
    branch staging
    checkout staging
    commit id: "release candidate" tag: "v1.4.0-rc.1"
    checkout dev
    branch production
    checkout production
    merge staging id: "PR #43" tag: "v1.4.0"

Trunk-based development

gitGraph
    commit id: "base"
    commit id: "M1"
    branch feature-search
    checkout feature-search
    commit id: "F1"
    commit id: "F2"
    checkout main
    merge feature-search id: "PR #51"
    commit id: "M2"
    branch release-1-4
    checkout release-1-4
    commit id: "release candidate" tag: "v1.4.0-rc.1"
    checkout main
    merge release-1-4 id: "PR #52" tag: "v1.4.0"

Ambientes efímeros por PR

gitGraph
    commit id: "base"
    branch feature-search
    checkout feature-search
    commit id: "S1"
    commit id: "preview PR #57 listo"
    checkout main
    branch feature-profile
    checkout feature-profile
    commit id: "P1"
    commit id: "preview PR #58 listo"
    checkout main
    merge feature-search id: "PR #57"
    merge feature-profile id: "PR #58"

Gestión de datos

Los datos y las dependencias externas determinan qué tan fiel puede ser cada ambiente de prueba, especialmente cuando el ambiente nace para un PR y desaparece al terminar.

Cuando contamos con ambientes persistentes, la información puede crecer de forma orgánica, ser administrada por un equipo de datos o provenir de una sincronización controlada desde producción. Con procedimientos repetibles.

En los ambientes efímeros el desafío cambia. La infraestructura se crea de forma dinámica para cada PR, por lo que también se debe producir dinámicamente una fuente de datos útil. La factibilidad del patrón depende, en gran medida, de qué tan fácil sea crear un equivalente de las fuentes de datos productivas.

Por eso, antes de adoptar ambientes efímeros, Desarrollo, QA, Datos y Operaciones deben acordar qué datos necesita cada prueba, cómo se generan, cuánto tardan en prepararse y qué dependencias se pueden emular. Esa conversación define si el ambiente será una validación confiable o solo una aproximación superficial.

¿Existe una mejor opción?

No existe un flujo de ramas superior en todos los contextos.

Elegir un modelo es acordar un lenguaje común: qué representa cada rama, qué controles debe pasar un PR, cómo se identifica una versión y cuándo se despliega. Un flujo simple, visible y entendido por Desarrollo y Operaciones es más valioso que seguir una receta popular que no encaja con la organización.

Práctica guiada: crear el repositorio y subir el código

CodeCommit

Consola

  1. Iniciar sesión en la consola de AWS en console.aws.amazon.com.
  2. Abrir CodeCommit.
  3. Confirmar que la región seleccionada (esquina superior derecha) es la misma que indicó el instructor. El taller usa una única región para todos los recursos.

Usaremos la región us-east-2.

Crear el repositorio

  1. Pulsar Create repository.
  2. En Repository name, escribir taller-aws-<su-nombre>. Usar el primer nombre en minúsculas y sin acentos (por ejemplo: taller-aws-carlos).
  3. En Description (opcional), escribir una descripción breve, por ejemplo: Repositorio del taller AWS DevOps — Semana 1.
  4. Dejar las demás opciones con sus valores predeterminados y pulsar Create.

CodeCommit crea el repositorio vacío en segundos y lleva a la vista principal del repositorio.

Ejercicio 1

Clonar, conectar y subir el código

Clonar el repositorio https://github.com/cloudbridgeuy/courses desde GitHub, crear un repositorio de CodeCommit llamado taller-aws-<su-nombre>, agregarlo como remoto, y subir la rama main.

Ejercicio 2

Crear una rama y encontrar su commit

Desde la consola de CodeCommit, crear la rama dev a partir de main. Luego localizar el ID del commit más reciente en esa rama.

Problema: ¿Como construir de forma reproducible?

El código fuente no se despliega directamente: primero se transforma en un artefacto desplegable. En este ejemplo, el artefacto es una imagen de contenedor construida a partir del Dockerfile en la raíz del repositorio.

Respuesta en AWS: CodeBuild y Amazon ECR

¿Qué expresa un buildspec.yml?

Un buildspec.yml es una especificación YAML que funciona como el pequeño DSL de CodeBuild: declara las fases del trabajo y los comandos que se ejecutan en cada una.

version: 0.2

phases:
  install:
    commands:
      - npm ci
  build:
    commands:
      - npm test
      - docker build -t app:$IMAGE_TAG .
  • version selecciona la versión del formato de buildspec.
  • phases organiza el proceso; las fases permitidas son: install, pre_build, build y post_build.
  • commands contiene la lista de órdenes de shell de cada fase, ejecutadas en orden.
  • También puede declarar env, artifacts, cache y reports.

¿Qué es Amazon ECR?

Amazon Elastic Container Registry (ECR) es el registro de imágenes de contenedores de AWS. Como DockerHub

Una vez construida la imagen Docker, hay que guardarla en algún lugar. Amazon ECR (Elastic Container Registry) es el servicio de AWS para almacenar imágenes Docker de forma privada y segura. Cuando ECS necesite lanzar el contenedor en la Semana 3, irá a buscar la imagen directamente a ECR.

Artefactos desplegables: construir una vez, promover muchas veces

El objetivo es solo producir el artefacto a desplegar una vez, para luego promoverlo entre ambientes.

La realidad es que no siempre se sigue esta práctica, y lo que termina pasando es que se termina reconstruyendo el artefacto en cada fase de su ciclo de vida. Algunas veces hay alguna razón para hacerlo, pero otras veces es simplemente un error.

Lo ideal, es que promovamos un mismo artefacto a través de distintos ambientes. Si es necesario que se comporte distinto en cada ambiente (se conecte a distintos servicios de terceros, bases de datos, nivel de logging, etc.) estos cambios de comportamiento deben producirse a través de cambios en su configuración, las cuales puede absorber de diversas maneras: variables de entorno, argumentos, archivos de configuración, etc.

Del código a la imagen publicada

Ahora que tenemos el código en un lugar que controlamos, tenemos que producir el artefacto desplegable de este proyecto: una imagen de contenedor.

%%{init: {"flowchart": {"defaultRenderer": "elk", "nodeSpacing": 40, "rankSpacing": 55, "padding": 12}, "themeVariables": {"clusterBkg": "#fdf4ff", "clusterBorder": "#c925d1", "surface0": "#fdf4ff", "border0": "#c925d1", "edgeLabelBackground": "#ffffff"}}}%%
flowchart LR
    subgraph repo["<img src='/static/aws-codecommit.svg' width='40' height='40' /> CodeCommit"]
        direction TB
        source["Código fuente"]
        spec["buildspec.yml"]
    end

    subgraph cb["<img src='/static/aws-codebuild.svg' width='40' height='40' /> CodeBuild"]
        direction LR
        dbuild["<img src='/static/docker.svg' width='42' /><br/>docker build"]
        image[["Imagen Docker"]]
        dpush["<img src='/static/docker.svg' width='42' /><br/>docker push"]
        dbuild ==> image ==> dpush
    end

    ecr[("<img src='/static/aws-ecr.svg' width='44' height='44' /><br/>Amazon ECR")]

    source --> dbuild
    spec -.->|"fases y comandos"| dbuild
    dpush ==> ecr

    classDef repoNode fill:#ffffff,stroke:#c925d1,color:#4a044e
    classDef dockerNode fill:#eff8ff,stroke:#2396ed,color:#0c4a6e
    classDef artifactNode fill:#f1f5f9,stroke:#475569,color:#0f172a
    classDef ecrNode fill:#fff7ed,stroke:#ed7100,stroke-width:2px,color:#7c2d12
    class source,spec repoNode
    class dbuild,dpush dockerNode
    class image artifactNode
    class ecr ecrNode

Un solo build, muchas etiquetas

  • Mismo artefacto en local y en producción.
  • Evitar reconstruir en cada fase (tiempo, y bytes distintos.)
  • Busquemos re-etiquetar, guiados por tags, labels y el digest de ECR.
%%{init: {"flowchart": {"nodeSpacing": 25, "rankSpacing": 40}}}%%
flowchart LR
    build["docker build<br/>(una sola vez)"] ==> img[("Imagen<br/>sha256:9f2c…")]
    img -->|"pr-123"| pr["Ambiente efímero"]
    img -->|"staging"| stg["Staging"]
    img ==>|"v1.4.0"| prod["Producción"]
    classDef dockerNode fill:#eff8ff,stroke:#2396ed,color:#0c4a6e
    classDef artifactNode fill:#f1f5f9,stroke:#475569,color:#0f172a
    classDef envNode fill:#ffffff,stroke:#94a3b8,color:#0f172a
    classDef prodNode fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#14532d
    class build dockerNode
    class img artifactNode
    class pr,stg envNode
    class prod prodNode

Mono-repo: build único por servicio

  • La identidad no es el commit: es el tree hash del contenido.
  • ¿Ya existe en ECR? Re-etiquetar. ¿No existe? Construir.
  • En el merge, solo se despliega lo que realmente cambió.
%%{init: {"flowchart": {"nodeSpacing": 25, "rankSpacing": 40}}}%%
flowchart LR
    push["push al PR"] --> hash["tree hash<br/>por servicio"]
    hash --> q{"¿existe<br/>en ECR?"}
    q -->|"sí"| retag["re-etiquetar<br/>(segundos)"]
    q -->|"no"| build["build + push"]
    retag ==> env["Ambiente efímero<br/>con los 3 servicios"]
    build ==> env
    classDef plainNode fill:#ffffff,stroke:#94a3b8,color:#0f172a
    classDef decisionNode fill:#fff7ed,stroke:#ed7100,color:#7c2d12
    classDef fastNode fill:#f0fdf4,stroke:#16a34a,color:#14532d
    classDef dockerNode fill:#eff8ff,stroke:#2396ed,color:#0c4a6e
    class push,hash,env plainNode
    class q decisionNode
    class retag fastNode
    class build dockerNode

Como obtener el tree-hash

❯ TREE_SHA=$(git rev-parse "HEAD:crates/server" | cut -c1-12)
❯ echo $TREE_SHA
303776a4ed6a
❯ git rev-parse "HEAD:crates/server" "HEAD:crates" "HEAD:crates/apps"
303776a4ed6ace5e887a17c3f464607601929bfb
5d43ec0a9ceb0cc60fe160f0e501beafb88567fc
b4067697c8594c8cdce9e37e4fc8e4512a837853
❯ TREE_SHA=$(git rev-parse "HEAD:crates/server" "HEAD:crates" "HEAD:crates/apps" \
  | git hash-object --stdin \
  | cut -c1-12)
❯ echo $TREE_SHA
78eb2d011698

El Dockerfile no es solo de los desarrolladores

  • Multi-stage: la imagen final lleva solo lo mínimo.
  • Dependencias: registro interno antes que PPA público.
  • Imágenes base: ECR Public o registro propio, no Docker Hub.
  • Pins: digest de la base + versiones de apt, siempre juntos.
  • Imagen base corporativa, pre-cargada en CI.

Un registro de artefactos administrado

Mantener un Artifact Registry interno tampoco es una tarea sencilla, pero de realizarlo correctamente, es algo muy poderoso. AWS nos puede ayudar con la gestión.

  • AWS CodeArtifact: registry interno administrado: npm, PyPI, Maven, NuGet, Cargo
  • External connections: el paquete se descarga del upstream público una sola vez, y queda retenido
  • ECR pull-through cache: lo mismo para imágenes base: Docker Hub, ECR Public, GHCR
  • Los paquetes de sistema (apt) quedan fuera — para eso, la imagen base corporativa

Automatizr linting de Dockerfiles con hadolint

  • Codifica estas prácticas como reglas verificables: por ejemplo DL3008 (pins de apt), DL3006/DL3007 (imagen base sin fijar), y ShellCheck en cada RUN.
  • En el editor: extensión del IDE o LSP, mientras se escribe.
  • En CI: una línea en pre_build; cualquier advertencia corta el build antes de construir nada.
  • Las excepciones quedan visibles y revisables: # hadolint ignore=… o .hadolint.yaml en el repositorio.

Cache de build en CodeBuild

  • Local: capas del host anterior — simple, pero best effort.
  • S3: rutas del buildspec.yml — entre hosts, con transferencia.
  • Registro: BuildKit publica el cache en ECR (:cache) — cualquier host.
%%{init: {"flowchart": {"nodeSpacing": 12, "rankSpacing": 40}}}%%
flowchart LR
    local["Cache local"] -.-> cb["CodeBuild"]
    s3[("Cache S3")] --> cb
    reg[("ECR :cache")] ==> cb
    cb ==> out[("Imagen publicada")]
    classDef plainNode fill:#ffffff,stroke:#94a3b8,color:#0f172a
    classDef s3Node fill:#f0fdf4,stroke:#16a34a,color:#14532d
    classDef ecrNode fill:#fff7ed,stroke:#ed7100,stroke-width:2px,color:#7c2d12
    classDef cbNode fill:#fdf4ff,stroke:#c925d1,color:#4a044e
    classDef artifactNode fill:#f1f5f9,stroke:#475569,color:#0f172a
    class local plainNode
    class s3 s3Node
    class reg ecrNode
    class cb cbNode
    class out artifactNode

Ejercicio 3

Crear el repositorio de imágenes

Crear un repositorio privado en Amazon ECR con el nombre taller-aws-<su-nombre>.

Ejercicio 4

Ejecutar la primera build

Configurar un proyecto de CodeBuild que lea el repositorio de CodeCommit, construya la imagen Docker usando el buildspec.yml incluido en el código, y la publique en el repositorio de ECR. Ejecutar el build y verificar que la imagen aparece en ECR con la etiqueta latest.

ECR más allá del push: lifecycle

La retención de imágenes es una política de la empresa.

%%{init: {"flowchart": {"nodeSpacing": 25, "rankSpacing": 45}}}%%
flowchart LR
    ecr[("<img src='/static/aws-ecr.svg' width='40' height='40' /><br/>repositorio")]
    ecr --> q{"¿qué regla<br/>lo limpia?"}
    q -->|"por tiempo<br/>(&gt; 90 días)"| del["borra también la<br/>imagen en producción"]
    del --> fail["escalar → ✗ pull falla"]
    q -->|"últimas N, y<br/>release-* protegido"| keep["lo desplegado<br/>siempre existe"]
    keep --> ok["escalar → ✓ pull"]
    classDef ecrNode fill:#fff7ed,stroke:#ed7100,stroke-width:2px,color:#7c2d12
    classDef decisionNode fill:#fff7ed,stroke:#ed7100,color:#7c2d12
    classDef badNode fill:#fef2f2,stroke:#dc2626,color:#7f1d1d
    classDef fastNode fill:#f0fdf4,stroke:#16a34a,color:#14532d
    class ecr ecrNode
    class q decisionNode
    class del,fail badNode
    class keep,ok fastNode

Hay que tener cuidado con la limpieza de imagenes por tiempo.

Mitigación: usar las "últimas N" en vez de días, tags de release protegidos, re-tag al promocionar, preview antes de aplicar.

ECR más allá del push: replicación

Cada push a la región de origen se copia solo.

Clave de un plan de Disaster Recovery.

%%{init: {"flowchart": {"nodeSpacing": 30, "rankSpacing": 55}}}%%
flowchart LR
    push["<img src='/static/docker.svg' width='42' /><br/>docker push"]
    push ==> src[("<img src='/static/aws-ecr.svg' width='40' height='40' /><br/>us-east-2<br/>(origen)")]
    src -.->|"réplica automática"| west[("<img src='/static/aws-ecr.svg' width='40' height='40' /><br/>us-west-2")]
    src -.->|"réplica automática"| acct[("<img src='/static/aws-ecr.svg' width='40' height='40' /><br/>otra cuenta")]
    west --> dr["DR: recrear el ambiente<br/>sin la región caída"]
    classDef dockerNode fill:#eff8ff,stroke:#2396ed,color:#0c4a6e
    classDef ecrNode fill:#fff7ed,stroke:#ed7100,stroke-width:2px,color:#7c2d12
    classDef fastNode fill:#f0fdf4,stroke:#16a34a,color:#14532d
    class push dockerNode
    class src,west,acct ecrNode
    class dr fastNode

Se replican los pushes, no los borrados: cada destino define su propia lifecycle policy.

ECR más allá del push: acceso

En un pull entre cuentas deben abrirse dos puertas; lo público va por Amazon ECR Public.

%%{init: {"flowchart": {"nodeSpacing": 30, "rankSpacing": 50}, "themeVariables": {"clusterBkg": "#f8fafc", "clusterBorder": "#94a3b8", "edgeLabelBackground": "#ffffff"}}}%%
flowchart LR
    subgraph consumidora["cuenta consumidora"]
        ecs["servicio ECS"]
        iam["puerta 1: IAM del<br/>task execution role"]
        ecs --> iam
    end
    subgraph shared["cuenta shared services"]
        pol["puerta 2: repository policy<br/>solo pull + aws:PrincipalOrgID"]
        repo[("<img src='/static/aws-ecr.svg' width='40' height='40' /><br/>ECR privado")]
        pol --> repo
    end
    iam ==>|"pull"| pol
    pub[("<img src='/static/aws-ecr.svg' width='40' height='40' /><br/>ECR Public")] -->|"pull anónimo"| world["cualquiera, sin<br/>cuenta de AWS"]
    classDef plainNode fill:#ffffff,stroke:#94a3b8,color:#0f172a
    classDef gateNode fill:#fefce8,stroke:#ca8a04,color:#713f12
    classDef ecrNode fill:#fff7ed,stroke:#ed7100,stroke-width:2px,color:#7c2d12
    class ecs,world plainNode
    class iam,pol gateNode
    class repo,pub ecrNode

ECR más allá del push: escaneo

Búsqueda continua de CVEs conocidos (Amazon Inspector). Findings + agentes → remediaciones como PRs automatizadas, sobre el mismo CI/CD.

%%{init: {"flowchart": {"nodeSpacing": 25, "rankSpacing": 45}}}%%
flowchart LR
    ecr[("<img src='/static/aws-ecr.svg' width='40' height='40' /><br/>imagen")]
    ecr --> insp["Amazon Inspector<br/>escaneo continuo"]
    insp -->|"CVE nuevo"| finding["finding"]
    finding --> agent["agente"]
    agent -->|"PR automatizada"| cc["<img src='/static/aws-codecommit.svg' width='40' height='40' /><br/>repo"]
    cc --> cb["<img src='/static/aws-codebuild.svg' width='40' height='40' /><br/>build"]
    cb ==>|"imagen corregida"| ecr
    classDef ecrNode fill:#fff7ed,stroke:#ed7100,stroke-width:2px,color:#7c2d12
    classDef plainNode fill:#ffffff,stroke:#94a3b8,color:#0f172a
    classDef badNode fill:#fef2f2,stroke:#dc2626,color:#7f1d1d
    classDef agentNode fill:#faf5ff,stroke:#9333ea,color:#581c87
    classDef repoNode fill:#ffffff,stroke:#c925d1,color:#4a044e
    classDef fastNode fill:#f0fdf4,stroke:#16a34a,color:#14532d
    class ecr ecrNode
    class insp plainNode
    class finding badNode
    class agent agentNode
    class cc repoNode
    class cb fastNode

Ejercicio 5

Activar el cache local del proyecto

Editar el proyecto de CodeBuild para activar el cache local con los modos SourceCache y DockerLayerCache. Ejecutar dos builds seguidos y comparar sus duraciones en el historial del proyecto.

Ejercicio 6

Servir las imágenes base desde nuestro registro

Configurar un pull-through cache de la galería pública de ECR, y apuntar las dos líneas FROM del Dockerfile a nuestro registro privado. Al terminar, ningún build vuelve a descargar rust ni debian desde Docker Hub.