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

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.**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1736878938723/6c5b8a68-0a03-45aa-9192-768ac3e80394.png align="center")

## 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

```bash
.
├── 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:

```dockerfile
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:

```bash
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

```yaml
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

```dockerfile
# Ú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

```bash
# 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:
    

```dockerfile
# 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/
```

2. **Cache de pip**: Usar `--no-cache-dir` para reducir el tamaño de la imagen.
    
3. **Limpieza**: Eliminar archivos innecesarios después de la instalación.
    

## Resultado

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1736895421814/5114a2b6-c5c3-430d-9147-b2d78252f5a4.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1736897497926/2b82659d-0fe1-4455-9c90-8260e70b53b8.png align="center")

Si quiero ejecución manual usen en gitlab-ci `when:manual`

```yaml
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
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1736895325706/eababdf6-24f4-4e19-9ab4-fef1d08e8fd7.png align="center")

## 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

* [Python Alpine Docker Hub](https://hub.docker.com/_/python)
    
* [Alpine Linux Packages](https://pkgs.alpinelinux.org/packages)
    
* [Docker Multi-stage Builds](https://docs.docker.com/build/building/multi-stage/)
    
* [Official Docker Bake Docs](https://docs.docker.com/engine/reference/commandline/buildx_bake/)
    

# Video

%[https://youtu.be/hErnEGOJzdw]
