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:
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:
services:
a:
build:
target: service_a
b:
build:
target: service_bUsar 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:
FROM alpine
RUN /bin/sh -c apk add --update --no-cache opensslb.Dockerfile:
FROM service_a
# compilar servicio bArchivo de Compose:
services:
a:
image: service_a
build:
dockerfile: a.Dockerfile
b:
image: service_b
build:
dockerfile: b.DockerfileEl 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:
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:
FROM base_image
# `base_image` no se resuelve como una imagen real. Se utiliza para apuntar a un contexto adicional con nombre.
# compilar servicio bArchivo de Compose:
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 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.
$ 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:
{
...
"plugins": {
"compose": {
"build": "bake"
}
}
...
}