# Compilar imágenes dependientes





Para reducir el tiempo de carga/descarga (push/pull) y el peso de las imágenes, una práctica común para las aplicaciones de Compose consiste en que los servicios compartan capas base tanto como sea posible. Normalmente, se selecciona la misma imagen base del sistema operativo para todos los servicios. Pero también puedes dar un paso más allá compartiendo capas de imágenes cuando estas comparten los mismos paquetes del sistema. El desafío a abordar es evitar repetir exactamente la misma instrucción del Dockerfile en todos los servicios.

A modo de ilustración, esta página asume que deseas que todos tus servicios se compilen con una imagen base de `alpine` e instalen el paquete del sistema `openssl`.

## Dockerfile multi-etapa (multi-stage)

El enfoque recomendado consiste en agrupar la declaración compartida en un solo Dockerfile y utilizar las características de multi-etapa (multi-stage) de modo que las imágenes de los servicios se compilen a partir de esta declaración compartida.

Dockerfile:

```dockerfile
FROM alpine as base
RUN /bin/sh -c apk add --update --no-cache openssl

FROM base as service_a
# compilar servicio a
...

FROM base as service_b
# compilar servicio b
...
```

Archivo de Compose:

```yaml
services:
  a:
    build:
      target: service_a
  b:
    build:
      target: service_b
```

## Usar la imagen de otro servicio como imagen base

Un patrón popular es reutilizar la imagen de un servicio como imagen base en otro servicio.
Dado que Compose no analiza el Dockerfile, no puede detectar automáticamente esta dependencia entre servicios para ordenar correctamente la ejecución de la compilación.

a.Dockerfile:

```dockerfile
FROM alpine
RUN /bin/sh -c apk add --update --no-cache openssl
```

b.Dockerfile:

```dockerfile
FROM service_a
# compilar servicio b
```

Archivo de Compose:

```yaml
services:
  a:
    image: service_a
    build:
      dockerfile: a.Dockerfile
  b:
    image: service_b
    build:
      dockerfile: b.Dockerfile
```

El antiguo Docker Compose v1 solía compilar imágenes de forma secuencial, lo que hacía que este patrón fuera utilizable directamente. Compose v2 utiliza BuildKit para optimizar las compilaciones y compilar imágenes en paralelo, por lo que requiere una declaración explícita.

El enfoque recomendado es declarar la imagen base dependiente como un contexto de compilación adicional:

Archivo de Compose:

```yaml
services:
  a:
    image: service_a
    build:
      dockerfile: a.Dockerfile
  b:
    image: service_b
    build:
      dockerfile: b.Dockerfile
      additional_contexts:
        # `FROM service_a` se resolverá como una dependencia del servicio "a", el cual debe compilarse primero
        service_a: "service:a"
```

Con el atributo `additional_contexts`, puedes hacer referencia a una imagen compilada por otro servicio sin necesidad de nombrarla explícitamente:

b.Dockerfile:

```dockerfile
FROM base_image
# `base_image` no se resuelve como una imagen real. Se utiliza para apuntar a un contexto adicional con nombre.

# compilar servicio b
```

Archivo de Compose:

```yaml
services:
  a:
    build:
      dockerfile: a.Dockerfile
      # la imagen compilada se etiquetará como <project_name>_a
  b:
    build:
      dockerfile: b.Dockerfile
      additional_contexts:
        # `FROM base_image` se resolverá como una dependencia del servicio "a", el cual debe compilarse primero
        base_image: "service:a"
```

## Compilar con Bake

El uso de [Bake](/build/bake/) permite pasar la definición de compilación completa para todos los servicios y orquestar la ejecución de la compilación de la manera más eficiente.

Para habilitar esta función, ejecuta Compose con la variable `COMPOSE_BAKE=true` establecida en tu entorno.

```console
$ COMPOSE_BAKE=true docker compose build
[+] Building 0.0s (0/1)
 => [internal] load local bake definitions                                 0.0s
...
[+] Building 2/2 manifest list sha256:4bd2e88a262a02ddef525c381a5bdb08c83  0.0s
  ✔ service_b  Built                                                        0.7s
  ✔ service_a  Built
```

Bake también se puede seleccionar como el constructor por defecto editando tu archivo de configuración `$HOME/.docker/config.json`:

```json
{
  ...
  "plugins": {
    "compose": {
      "build": "bake"
    }
  }
  ...
}
```

## Recursos adicionales

- [Referencia de compilación de Docker Compose](/reference/cli/docker/compose/build/)
- [Más información sobre Dockerfiles multi-etapa (multi-stage)](/build/building/multi-stage/)

