Implementar imágenes multi-arquitectura ECR es el paso fundamental para cualquier equipo que busque optimizar sus costes operativos en la nube. En el mundo del Cloud Computing, la eficiencia no es negociable. Es un entorno donde todo parece ideal hasta que, por un descuido, te llega una factura de seis cifras. Por eso, optimizar el rendimiento por dólar no es solo una buena práctica, es una necesidad de supervivencia.
En este artículo, veremos cómo transformar un pipeline estándar en uno capaz de servir a diferentes arquitecturas de forma transparente usando imágenes multi-arquitectura ECR.
1. El Estado Inicial: El Reinado de x86
Imaginemos un flujo de trabajo que es lineal y especializado:
- CI/CD: AWS CodeBuild utiliza un entorno estándar de Linux x86_64.
- Artefactos: Generamos imágenes Docker compiladas exclusivamente para arquitectura Intel/AMD.
- Infraestructura: Un Auto Scaling Group (ASG) único compuesto por instancias tradicionales Intel. Podría ser cualquier tipo de orquestación pero imaginemos que es ECS.
- Limitación: No podemos desplegar en nodos ARM, ya que el binario/imagen fallaría al ejecutarse.

Vamos a analizar un servicio que usa una imagen de DockerHub.
Actualmente, si inspeccionamos la imagen base que utilizamos (eclipse-temurin:xx-jre-alpine), confirmamos que está limitada a una sola arquitectura:
# Inspeccionando la arquitectura de la imagen actual
> docker inspect <ID_DE_CUENTA>.dkr.ecr.eu-west-1.amazonaws.com/eclipse-temurin:XX-jre-alpine --format='{{.Architecture}}'
# Resultado: amd64
El problema surge al intentar desplegar en instancias ARM (como Graviton o equipos locales M1/M2). Al no existir capas para ARM en el manifiesto actual, el despliegue fallará porque el contenedor no encuentra las instrucciones compatibles con el procesador.
Vamos a ver un ejemplo de un buildspec.yaml, el fichero que procesará el servicio CodeBuild para hacer build de las imágenes. Este ejemplo muestra un CodeBuild que hace build de imágenes en ECR de imágenes AMD64 exclusivamente
version: 0.2
env:
variables:
ECR: "xxxxxxxx.dkr.ecr.xxxxxxxxx.amazonaws.com"
SERVICE: "my-service"
phases:
install:
runtime-versions:
java: xxxxxxxxxx
pre_build:
commands:
- $(aws ecr get-login --no-include-email --region eu-west-1)
- DOCKER_URI="${ECR}/${SERVICE}"
...
...
...
build:
commands:
...
...
...
# Build the docker image of the application
- docker build -f infrastructure/docker/Dockerfile -t ${SERVICE}:current --build-arg ECR=${ECR} .
post_build:
commands:
...
...
- echo $DOCKER_TAGS | xargs -d , -n 1 sh -c 'for tag do docker tag ${SERVICE}:current ${DOCKER_URI}:$tag; docker push ${DOCKER_URI}:$tag; done' _
2. El Objetivo: Flexibilidad Total con Multi-arquitectura
El “Después” no consiste en abandonar x86, sino en ser agnósticos. Entiéndase agnósticos en el sentido de que podremos desplegar servicios de ECS en AMD64 o ARM indistintamente. La meta es que cada vez que el CI/CD haga un push a Amazon ECR, no suba una imagen, sino un Manifest List.

Este manifiesto permitirá que:
- Si una instancia Intel pide la imagen, ECR le entrega la versión x86.
- Si una instancia Graviton pide la imagen, ECR le entrega la versión ARM64.
- ECS gestione el tráfico inteligentemente mediante placement constraints y atributos de capacidad.
Para lograr esta transición, los pilares del cambio son:
3. Los Detalles Técnicos del Cambio
| Componente | Acción de Mejora |
| AWS CodeBuild | Activación del soporte para Docker “buildx” o uso de flotas mixtas. |
| Docker Buildx | Uso de docker buildx build --platform linux/amd64,linux/arm64. |
| Amazon ECR | Almacenamiento de imágenes bajo un único tag que referencia a ambas arquitecturas. |
| Orquestación | Configuración de etiquetas en ECS para mover servicios gradualmente a Graviton. |
4. Beneficios Inmediatos
- Reducción de Costes: Las instancias Graviton son inherentemente más baratas por el mismo nivel de cómputo.
- Resiliencia: Capacidad de mover cargas de trabajo entre diferentes tipos de familias de instancias según disponibilidad de spot o precio.
Nota importante: La migración no requiere cambiar el código fuente de las aplicaciones Java, gracias a que la JVM aísla la arquitectura, pero sí requiere que nuestras imágenes base (como
eclipse-temurin) y librerías nativas sean compatibles.
5. Configurar CodeBuild para hacer build multi plataforma
version: 0.2
env:
variables:
ECR: "xxxxxxxx.dkr.ecr.xxxxxxxxx.amazonaws.com"
SERVICE: "my-service"
phases:
install:
runtime-versions:
java: xxxxxxxxxx
pre_build:
commands:
- $(aws ecr get-login --no-include-email --region eu-west-1)
- DOCKER_URI="${ECR}/${SERVICE}"
# Descargar e instalar Buildx como plugin del CLI
- export DOCKER_CLI_EXPERIMENTAL=enabled
- mkdir -vp ~/.docker/cli-plugins/
- curl --silent -L "https://github.com/docker/buildx/releases/download/v0.12.1/buildx-v0.12.1.linux-amd64" > ~/.docker/cli-plugins/docker-buildx
- chmod a+x ~/.docker/cli-plugins/docker-buildx
# Verificar que ahora sí aparece en la lista
- docker buildx version
# Instalar emuladores para permitir compilar ARM64 en hosts Intel
- docker run --privileged --rm tonistiigi/binfmt --install all
# Crear el constructor (builder) usando el driver 'docker-container'
# Este driver es obligatorio para multi-arquitectura real
- docker buildx create --use --name mybuilder --driver docker-container
- docker buildx inspect --bootstrap
build:
commands:
...
...
...
post_build:
commands:
# Definir etiquetas según la rama
if [ "$GIT_BRANCH" = "master" ]; then
DOCKER_TAGS="${GIT_COMMIT},${RELEASE_NAME},latest"
else
DOCKER_TAGS="${GIT_COMMIT},${RELEASE_NAME}"
fi
# Convertir la lista en flags de Docker (-t imagen:tag1 -t imagen:tag2...)
- TAG_FLAGS=$(echo $DOCKER_TAGS | sed "s|,| -t ${DOCKER_URI}:|g" | sed "s|^|-t ${DOCKER_URI}:|")
- >
docker buildx build
--platform linux/amd64,linux/arm64
-f infrastructure/docker/Dockerfile
${TAG_FLAGS}
--build-arg ECR=${ECR}
--push .
Resumen: De x86 a la libertad Multi-arquitectura
En esta guía, hemos transformado un pipeline de CI/CD tradicional en uno preparado para el futuro. Estos son los hitos que hemos cubierto:
- El punto de partida: Analizamos cómo nuestro flujo actual en AWS CodeBuild generaba artefactos limitados a la arquitectura AMD64.
- La necesidad del cambio: Identificamos que las imágenes basadas en
eclipse-temurin:17.0.13_11-jre-alpinecompiladas para x86 no pueden ejecutarse en instancias Graviton, lo que nos impedía ahorrar costes. - La solución técnica: Implementamos Docker Buildx para crear un “Manifest List” en Amazon ECR. Esto permite que una misma etiqueta de imagen sirva tanto a nodos Intel como a nodos ARM de forma automática.
Implementar imágenes multi-arquitectura ECR no es solo una mejora técnica; es una decisión estratégica que permite a tu equipo aprovechar el rendimiento superior de los procesadores ARM sin añadir complejidad al proceso de despliegue.
De todas maneras, siempre será necesario hacer los cambios poco a poco, donde el foco sea pequeño. Sería ideal poder probar que costes tenemos en global, que costes tenemos en este foco reducido, hacer la migración y luego poder comparar.
¿Te ha ayudado este artículo?
☕ Invítame a un café