Docker Compose Build

Intermedio
Docker
Docker
Actualizado: 04/05/2026

Build y Dockerfile en Docker compose

Hasta ahora has aprendido a construir imágenes usando el comando docker build directamente desde la terminal. Sin embargo, Docker Compose permite integrar el proceso de construcción directamente en el archivo compose.yaml, simplificando significativamente el flujo de trabajo de desarrollo.

flowchart LR
    YAML["compose.yaml<br/>service: backend<br/>build:<br/>  context: ./backend<br/>  dockerfile: Dockerfile<br/>  target: runtime<br/>  args:<br/>    NODE_VERSION: 24"] -->|docker compose build| BK["BuildKit<br/>+ buildx"]
    BK -->|cache mounts| L1["Layer cache<br/>local"]
    BK -->|secret mounts<br/>--mount=type=secret| SEC["(&quot;Secrets<br/>./secrets/.npmrc&quot;)"]
    BK --> IMG["Imagen<br/>proyecto-backend:latest"]
    IMG --> UP["docker compose up<br/>arranca contenedor"]
    UP --> RUN[Servicio en ejecución]
    style BK fill:#1d63ed,color:#fff
    style IMG fill:#1d63ed,color:#fff

La integración del build en Docker Compose elimina la necesidad de ejecutar comandos docker build separados, ya que Compose se encarga automáticamente de construir las imágenes cuando es necesario. Esta aproximación es especialmente útil en entornos de desarrollo donde necesitas reconstruir imágenes frecuentemente.

Configuración básica del build

Para integrar el build en tu archivo compose.yaml, utilizas la clave build en lugar de image dentro de la definición del servicio:

services:
  web:
    build: .
    ports:
      - "3000:3000"

En este ejemplo básico, Compose buscará un Dockerfile en el directorio actual (indicado por .) y lo utilizará para construir la imagen del servicio web.

Especificando el contexto y Dockerfile

Cuando necesitas mayor control sobre el proceso de build, puedes especificar explícitamente el contexto y la ubicación del Dockerfile:

services:
  api:
    build:
      context: ./backend
      dockerfile: Dockerfile.dev
    ports:
      - "8080:8080"
  
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"

El context define el directorio base que se enviará al daemon de Docker para la construcción, mientras que dockerfile específica qué archivo Dockerfile utilizar dentro de ese contexto.

Integración de build args

Los build arguments que aprendiste anteriormente también se pueden configurar directamente en el archivo Compose:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        - NODE_VERSION=20
        - BUILD_ENV=development
    environment:
      - APP_ENV=dev

Esto es equivalente a ejecutar:

docker build --build-arg NODE_VERSION=20 --build-arg BUILD_ENV=development .

Variables de entorno en build args

Puedes combinar variables de entorno con build args para mayor flexibilidad:

services:
  app:
    build:
      context: .
      args:
        - JAVA_VERSION=${JAVA_VERSION:-21}
        - BUILD_MODE=${BUILD_MODE:-development}

Con un archivo .env correspondiente:

JAVA_VERSION=21
BUILD_MODE=production

Target para multi-stage builds

Cuando utilizas multi-stage builds, puedes especificar qué stage construir:

services:
  app-dev:
    build:
      context: .
      target: development
    volumes:
      - ./src:/app/src
  
  app-prod:
    build:
      context: .
      target: production
    ports:
      - "8080:8080"

Esto permite tener diferentes configuraciones del mismo Dockerfile para distintos entornos.

Construcción automática y manual

Por defecto, Compose construye las imágenes automáticamente cuando ejecutas docker compose up si no existen. Sin embargo, puedes controlar este comportamiento:

Forzar reconstrucción:

docker compose up --build

Construir solo las imágenes sin arrancar servicios:

docker compose build

Construir un servicio específico:

docker compose build app

Ejemplo práctico completo

Aquí tienes un ejemplo que integra una aplicación Node.js con una base de datos PostgreSQL:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
  
  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        - NODE_VERSION=20
        - BUILD_ENV=development
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://user:password@db:5432/myapp
      - NODE_ENV=development
    depends_on:
      - db
    volumes:
      - ./src:/app/src
      - node_modules:/app/node_modules

volumes:
  postgres_data:
  node_modules:

El Dockerfile correspondiente podría ser:

ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine

ARG BUILD_ENV=production
ENV NODE_ENV=${BUILD_ENV}

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production

COPY . .

EXPOSE 3000
CMD ["npm", "start"]

Ventajas del build integrado

La integración del build en Docker Compose ofrece varias ventajas significativas:

  • Flujo simplificado: No necesitas recordar comandos de build separados
  • Configuración centralizada: Toda la configuración del proyecto está en un solo archivo
  • Gestión automática: Compose maneja las dependencias de construcción
  • Reutilización: Los build args y configuraciones se pueden reutilizar fácilmente
  • Entornos consistentes: Garantiza que todos los desarrolladores construyen las imágenes de la misma manera

Esta integración hace que el desarrollo con Docker sea mucho más eficiente, especialmente cuando trabajas con aplicaciones que requieren construcción frecuente durante el desarrollo.

Build con BuildKit y cache mounts

Compose v2 invoca BuildKit por defecto, lo que habilita las directivas --mount=type=cache y --mount=type=secret dentro de los Dockerfile. En entornos B2B con runners CI/CD compartidos esto reduce los tiempos de build entre un 40% y un 70% al persistir el caché de paquetes (~/.m2, ~/.npm, ~/.cache/pip) sin contaminar la imagen final:

services:
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
      target: runtime
      cache_from:
        - registry.empresa.es/backend:cache
      cache_to:
        - type=registry,ref=registry.empresa.es/backend:cache,mode=max
      args:
        JAVA_VERSION: "21"
      secrets:
        - github_token
secrets:
  github_token:
    file: ./secrets/github_token.txt

Las claves cache_from y cache_to permiten compartir el caché entre runners (GitHub Actions self-hosted, GitLab Runner, Jenkins agents) usando el propio registry corporativo como almacén distribuido. El valor mode=max exporta también las capas intermedias del multi-stage para que el siguiente build pueda saltar etapas costosas como mvn dependency:go-offline.

Multi-arch y plataformas con buildx

Cuando el cliente exige imágenes que corran en linux/amd64 y en linux/arm64 (servidores Graviton4 en AWS, Apple Silicon en desarrollo, Raspberry Pi en edge), Compose delega en buildx mediante el campo platforms:

services:
  api:
    build:
      context: .
      platforms:
        - linux/amd64
        - linux/arm64
      tags:
        - registry.empresa.es/api:1.4.2
        - registry.empresa.es/api:1.4

El primer docker compose build genera un manifest list OCI con ambas variantes y lo pública con docker compose push. La consultora puede cubrir multinube heterogéneo con un único pipeline.

Estrategia B2B: Compose para CI, Bake para release

Una pauta extendida en equipos DevOps maduros separa los compose.yaml por propósito. compose.yaml queda como entorno local del desarrollador con builds rápidos y volúmenes de hot reload. compose.ci.yaml se usa en pull requests con target: testing, healthchecks estrictos y sin bind mounts. Para releases productivos se sustituye Compose por Docker Bake (docker buildx bake) declarando los mismos servicios en docker-bake.hcl, lo que añade matrices de plataforma, firmado con cosign y generación de SBOM en una sola invocación. La portabilidad del Dockerfile entre los tres flujos se mantiene porque el contexto y los target son idénticos.

Fuentes y referencias

Documentación oficial y recursos externos para profundizar en Docker

Documentación oficial de Docker
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Docker es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de Docker

Explora más contenido relacionado con Docker y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Comprender cómo configurar la clave build en el archivo compose.yaml para construir imágenes automáticamente. Aprender a especificar el contexto y el Dockerfile para un control detallado del build. Utilizar build args y variables de entorno para parametrizar la construcción de imágenes. Manejar multi-stage builds mediante la opción target en Docker Compose. Conocer los comandos para construir imágenes automática o manualmente con Docker Compose.