Tener un repositorio privado de AWS ECR es muy útil para mantener las versiones de nuestra aplicación dentro de la nube y ejecutar tareas con ellas. Pero es bastante interesante mantener estas versiones a través de un motor CI/CD, así como etiquetarlas automáticamente para obtener un registro de nuestros cambios con nuestras versiones, y promoverlas entre nuestros diferentes entornos.
En este pequeño artículo, te mostraré cómo integrar una acción de push dentro de un flujo de trabajo de Github Actions. El momento en que debemos enviar nuestras imágenes depende del flujo de lanzamiento que hayamos diseñado para nuestra aplicación. En mi caso, generalmente configuro dos entornos para mis proyectos (desarrollo y producción), y publico automáticamente en el entorno de desarrollo cuando fusiono un Pull Request con la rama de desarrollo.
En ese momento es cuando genero una nueva imagen, que una vez probada en el entorno de desarrollo, a través de pruebas automáticas y manuales, la promoveré al entorno de producción. Para desplegar nuestras imágenes, suelo configurar un flujo de trabajo con estos pasos:

Let’s code
Con el diagrama anterior en mente, podemos comenzar a configurar nuestro archivo de Github Actions dentro de nuestro proyecto. Veamos el siguiente código:
# ./.github/workflows/develop_push.yml
name: "On merge inside develop"
on:
push:
branches:
- develop
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
jobs:
applytf:
runs-on: ubuntu-latest
name: "Apply TF"
permissions:
pull-requests: write
contents: read
defaults:
run:
working-directory: ./iac
steps:
- uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
- name: Terraform Init
id: init
run: terraform init
- name: Terraform apply
run: terraform apply -auto-approve -input=false
publishdocker:
name: "Build docker and publish to ECR"
needs: [ applytf ]
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./src
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Bump version and push tag
id: tag_version
uses: mathieudutour/github-tag-action@v6.1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
release_branches: "main,develop"
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_DEFAULT_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build, tag, and push image to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: example
IMAGE_TAG: ${{ steps.tag_version.outputs.new_version }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -t $ECR_REGISTRY/$ECR_REPOSITORY:latest -f .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
El primer trabajo aplica la infraestructura de Terraform dentro de nuestra cuenta de AWS. No es el objetivo principal del artículo, pero podemos revisar lo que está haciendo:
- En primer lugar, establece el directorio de trabajo dentro de la carpeta
./iac
. Esta carpeta contendrá todo nuestro código de Terraform que creará, junto con otros recursos, nuestro repositorio ECR privado. - El segundo paso inicializa el entorno de Terraform y descarga los diferentes proveedores y módulos que necesitará para aplicarlo.
- El paso final aplica la infraestructura de Terraform dentro de nuestra cuenta en la nube, pero ¿cómo? Si revisas todo el archivo, verás que al principio del archivo, definimos tres variables de entorno para conectarnos a nuestra cuenta de AWS. Estas credenciales son las que utilizará Terraform para ejecutar y desplegar la infraestructura.
El segundo trabajo depende de la ejecución del trabajo de Terraform. Paso a paso, aquí tenemos lo que está haciendo:
- Establece el directorio de trabajo en la carpeta
./src
. Suponemos que allí tenemos todo el código con nuestro archivoDockerfile
para construir nuestra imagen. - Incremento de versión y etiquetado. Quizás el paso más interesante de todos, con esta acción podemos crear automáticamente una versión mayor, menor o de parche. Creará la etiqueta en el punto específico del código y añadirá un registro a la etiqueta con los cambios desde la etiqueta anterior.
- Como puedes ver, puse la propiedad
release_branches
con los nombres de las ramas develop y main. Eso se debe a que expliqué al principio del artículo que generalmente promuevo la misma versión del entorno de desarrollo al entorno de producción (sin reconstruirla). Eso asegura que la versión lanzada a producción sea la misma que se ha probado en desarrollo. Enlace al código de la acción en Github: - Las dos acciones siguientes establecerán las credenciales para acceder a AWS en la próxima acción. Responderán con las credenciales necesarias y las claves temporales para permitir que el comando Docker envíe la imagen a nuestro ECR privado. Enlace al código de la acción en Github:
- Finalmente, construye la imagen Docker con el archivo
Dockerfile
ubicado dentro de la carpeta./src
, etiquetándola con dos etiquetas diferentes:latest
para configurarla como la última imagen disponible dentro del repositorio.- Código de versión de la acción de etiquetado. Luego, envía las imágenes al repositorio ECR y eso es todo.
TL;DR
Como podemos ver, la acción para enviar nuestras imágenes a un repositorio privado de ECR es muy sencilla, pero es más importante definir correctamente nuestros flujos de lanzamiento y establecer exactamente cuándo queremos enviarlas, y cuál es el ciclo de vida de las imágenes enviadas a nuestro servidor.
Este artículo se basa en la infraestructura escrita en .