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

Rossana SuarezRossana Suarez
3 min read

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.

Introducción

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

Estructura del Proyecto

.
├── Dockerfile
├── bake.hcl
└── .gitlab-ci.yml

El Dockerfile Base Optimizado

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

Configuración de Bake para Imágenes Alpine

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"
  }
}

Configuración de GitLab CI

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

Usando las Imágenes Alpine

# Última versión
FROM tunombre/python-alpine:3.12

# Versiones específicas
FROM tunombre/python-alpine:3.11
FROM tunombre/python-alpine:3.10

Comparación de Tamaños

Aquí una comparación del tamaño de las imágenes:

  • Python Alpine: ~100MB

  • Python Slim: ~200MB

  • Python Regular: ~900MB

Consideraciones Importantes

Cuando uses imágenes Alpine, ten en cuenta:

  1. Dependencias Nativas: Alpine usa musl libc en lugar de glibc, lo que puede causar problemas con algunas dependencias nativas.

  2. Paquetes del Sistema: Los nombres de los paquetes pueden diferir de Debian/Ubuntu.

  3. Compilación: Algunas dependencias pueden requerir compilación, por lo que necesitarás incluir build-base y otras herramientas de compilación.

Construcción Local

# 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

Optimizaciones Adicionales

  1. Multi-stage Builds: Para reducir aún más el tamaño:
# 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/
  1. Cache de pip: Usar --no-cache-dir para reducir el tamaño de la imagen.

  2. Limpieza: Eliminar archivos innecesarios después de la instalación.

Resultado

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

Conclusión

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

Recursos

Video

0
Subscribe to my newsletter

Read articles from Rossana Suarez directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rossana Suarez
Rossana Suarez

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 🔥