Construyendo Imágenes Docker Multi-Versión con Docker Buildx Bake

Soy Roxs 👩💻| Software Developer | DevOps | DevSecOps | en @295DevOps 🖼 Content Creator. No se puede crecer si no estas dispuesto a saltar a la zona de peligro 🔥
Search for a command to run...

Soy Roxs 👩💻| Software Developer | DevOps | DevSecOps | en @295DevOps 🖼 Content Creator. No se puede crecer si no estas dispuesto a saltar a la zona de peligro 🔥
No comments yet. Be the first to comment.
Cada minuto que un dev espera un pipeline es un minuto de foco perdido. Multiplicalo por cada commit, cada MR, cada persona del equipo... y de repente ese pipeline de 25 minutos es el impuesto más car

Si venís siguiendo mi contenido hace rato, sabés que hay una frase que repito hasta el cansancio: la mejor forma de aprender cloud es rompiendo cosas en la cloud. El problema siempre fue el mismo: par

Si me seguís hace un tiempo ya sabés que estoy metida hasta con todo el power con Kiro IDE: demos, integraciones con GitLab CI, bootcamp y todo lo que se te ocurra. Así que cuando me crucé con este po

Build with fire, deploy with power 🔥

Por @roxsross · roxs.dev Introducción ¿Cuántas veces mergeaste un cambio de infraestructura y te enteraste del problema en producción? ¿Cuántos security groups abiertos al mundo, cuántos IAM con * en

En el mundo de los contenedores, el tamaño importa. Las imágenes Alpine Linux son conocidas por ser extremadamente ligeras y seguras, lo que las hace ideales para entornos de producción. En este artículo, exploraremos cómo crear y mantener múltiples versiones de imágenes Python basadas en Alpine usando Docker Buildx Bake y GitLab CI.

Las imágenes Alpine de Python ofrecen varias ventajas:
Tamaño reducido (~ 50-100MB vs 900MB+ en imágenes basadas en Debian)
Menor superficie de ataque para vulnerabilidades
Mejor rendimiento en entornos cloud
Inicio más rápido de contenedores
.
├── Dockerfile
├── bake.hcl
└── .gitlab-ci.yml
Crearemos un Dockerfile optimizado para Alpine que incluye las dependencias necesarias para la mayoría de aplicaciones Python:
ARG IMAGE=python:3.12-alpine
FROM $IMAGE
LABEL maintainer="roxs@295devops.com"
# Instalamos solo las dependencias básicas necesarias
RUN apk add --no-cache \
git \
gcc \
build-base
# Creamos y usamos usuario no root
RUN addgroup -S python && adduser -S python -G python
USER python
WORKDIR /app
El archivo bake.hcl se configura específicamente para versiones Alpine:
variable "REGISTRY" {
default = "docker.io/tunombre/"
}
group "default" {
targets = ["py-3-12-alpine", "py-3-11-alpine", "py-3-10-alpine"]
}
target "py-3-12-alpine" {
dockerfile = "./Dockerfile"
tags = [
"${REGISTRY}python-alpine:3.12"
]
args = {
IMAGE = "python:3.12-alpine"
}
}
target "py-3-11-alpine" {
dockerfile = "./Dockerfile"
tags = ["${REGISTRY}python-alpine:3.11"]
args = {
IMAGE = "python:3.11-alpine"
}
}
target "py-3-10-alpine" {
dockerfile = "./Dockerfile"
tags = ["${REGISTRY}python-alpine:3.10"]
args = {
IMAGE = "python:3.10-alpine"
}
}
stages:
- build
.build:
image: docker:27.5.0
stage: build
variables:
DOCKER_HOST: "tcp://docker:2375"
DOCKER_TLS_CERTDIR: ""
BUILDX_NO_DEFAULT_ATTESTATIONS: 1
DOCKER_DRIVER: overlay2
DOCKER_BUILDKIT: 1
BUILDKIT_PROGRESS: plain
services:
- name: docker:27.5.0-dind
command: ["--tls=false"]
before_script:
- docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_TOKEN
- docker info
build:
extends: .build
parallel:
matrix:
- BUILD: ['py-3-12-alpine', 'py-3-11-alpine', 'py-3-10-alpine']
REGISTRY: ['docker.io/tunombre/']
script:
- docker buildx create --use
- REGISTRY=${REGISTRY} docker buildx bake --progress plain --push -f bake.hcl $BUILD
# Última versión
FROM tunombre/python-alpine:3.12
# Versiones específicas
FROM tunombre/python-alpine:3.11
FROM tunombre/python-alpine:3.10
Aquí una comparación del tamaño de las imágenes:
Python Alpine: ~100MB
Python Slim: ~200MB
Python Regular: ~900MB
Cuando uses imágenes Alpine, ten en cuenta:
Dependencias Nativas: Alpine usa musl libc en lugar de glibc, lo que puede causar problemas con algunas dependencias nativas.
Paquetes del Sistema: Los nombres de los paquetes pueden diferir de Debian/Ubuntu.
Compilación: Algunas dependencias pueden requerir compilación, por lo que necesitarás incluir build-base y otras herramientas de compilación.
# Construir todas las versiones
docker buildx bake -f bake.hcl
# Construir una versión específica
docker buildx bake -f bake.hcl py-3-12-alpine
# Construir y publicar
REGISTRY=docker.io/tunombre/ docker buildx bake --push -f bake.hcl
# Etapa de construcción
FROM python:3.12-alpine AS builder
RUN apk add --no-cache build-base
RUN pip install --no-cache-dir mypackage
# Etapa final
FROM python:3.12-alpine
COPY --from=builder /usr/local/lib/python3.12/site-packages/ /usr/local/lib/python3.12/site-packages/
Cache de pip: Usar --no-cache-dir para reducir el tamaño de la imagen.
Limpieza: Eliminar archivos innecesarios después de la instalación.


Si quiero ejecución manual usen en gitlab-ci when:manual
build:
extends: .build
when:manual
parallel:
matrix:
- BUILD: ['py-3-12-alpine', 'py-3-11-alpine', 'py-3-10-alpine']
REGISTRY: ['docker.io/tunombre/']
script:
- docker buildx create --use
- REGISTRY=${REGISTRY} docker buildx bake --progress plain --push -f bake.hcl $BUILD

Las imágenes Alpine ofrecen un excelente equilibrio entre tamaño y funcionalidad. Con Docker Buildx Bake y GitLab CI, podemos mantener fácilmente múltiples versiones de estas imágenes optimizadas.
La configuración que hemos cubierto permite:
Crear imágenes Python ligeras y seguras
Mantener múltiples versiones de forma automatizada
Optimizar el proceso de construcción y distribución