Compartir comentarios
Las respuestas se generan en base a la documentación.

Usar Docker Compose

Docker Compose es una herramienta que ayuda a definir y compartir aplicaciones de múltiples contenedores. Con Compose, puedes crear un archivo YAML para definir los servicios y, con un solo comando, puedes poner todo en marcha o destruirlo por completo.

La gran ventaja de utilizar Compose es que puedes definir la pila de tu aplicación en un archivo, mantenerlo en la raíz del repositorio de tu proyecto (ahora bajo control de versiones) y facilitar que otra persona colabore en tu proyecto. Solo necesitarían clonar tu repositorio e iniciar la aplicación utilizando Compose. De hecho, es muy común ver bastantes proyectos en GitHub/GitLab que hacen exactamente esto actualmente.

Crear el archivo de Compose

En el directorio getting-started-app, crea un archivo llamado compose.yaml.

├── getting-started-app/
│ ├── Dockerfile
│ ├── compose.yaml
│ ├── node_modules/
│ ├── package.json
│ ├── package-lock.json
│ ├── spec/
│ └── src/

Definir el servicio de la aplicación

En la parte 6, utilizaste el siguiente comando para iniciar el servicio de la aplicación.

$ docker run -dp 127.0.0.1:3000:3000 \
  -w /app -v ".:/app" \
  --network todo-app \
  -e MYSQL_HOST=mysql \
  -e MYSQL_USER=root \
  -e MYSQL_PASSWORD=secret \
  -e MYSQL_DB=todos \
  node:24-alpine \
  sh -c "npm install && npm run dev"

Ahora definirás este servicio en el archivo compose.yaml.

  1. Abre compose.yaml en un editor de texto o código, y comienza definiendo el nombre y la imagen del primer servicio (o contenedor) que deseas ejecutar como parte de tu aplicación. El nombre se convertirá automáticamente en un alias de red, lo que será útil al definir tu servicio MySQL.

    services:
      app:
        image: node:24-alpine
  2. Normalmente verás command cerca de la definición de image, aunque no existe un requisito de orden. Agrega command a tu archivo compose.yaml.

    services:
      app:
        image: node:24-alpine
        command: sh -c "npm install && npm run dev"
  3. Ahora migra la parte -p 127.0.0.1:3000:3000 del comando definiendo los puertos (ports) para el servicio.

    services:
      app:
        image: node:24-alpine
        command: sh -c "npm install && npm run dev"
        ports:
          - 127.0.0.1:3000:3000
  4. A continuación, migra tanto el directorio de trabajo (-w /app) como el mapeo de volumen (-v ".:/app") utilizando las definiciones working_dir y volumes.

    Una ventaja de las definiciones de volumen de Docker Compose es que puedes usar rutas relativas desde el directorio actual.

    services:
      app:
        image: node:24-alpine
        command: sh -c "npm install && npm run dev"
        ports:
          - 127.0.0.1:3000:3000
        working_dir: /app
        volumes:
          - ./:/app
  5. Por último, debes migrar las definiciones de las variables de entorno utilizando la clave environment.

    services:
      app:
        image: node:24-alpine
        command: sh -c "npm install && npm run dev"
        ports:
          - 127.0.0.1:3000:3000
        working_dir: /app
        volumes:
          - ./:/app
        environment:
          MYSQL_HOST: mysql
          MYSQL_USER: root
          MYSQL_PASSWORD: secret
          MYSQL_DB: todos

Definir el servicio MySQL

Ahora es el momento de definir el servicio MySQL. El comando que utilizaste para ese contenedor fue el siguiente:

$ docker run -d \
  --network todo-app --network-alias mysql \
  -v todo-mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=todos \
  mysql:8.0
  1. Primero define the nuevo servicio y llámalo mysql para que obtenga automáticamente el alias de red. Especifica también la imagen que se va a utilizar.

    services:
      app:
        # La definición del servicio app
      mysql:
        image: mysql:8.0
  2. A continuación, define el mapeo de volumen. Cuando ejecutaste el contenedor con docker run, Docker creó el volumen con nombre automáticamente. Sin embargo, eso no sucede cuando se ejecuta con Compose. Debes definir el volumen en la sección superior volumes: y luego especificar el punto de montaje en la configuración del servicio. Al proporcionar simplemente el nombre del volumen, se utilizarán las opciones predeterminadas.

    services:
      app:
        # La definición del servicio app
      mysql:
        image: mysql:8.0
        volumes:
          - todo-mysql-data:/var/lib/mysql
    
    volumes:
      todo-mysql-data:
  3. Por último, debes especificar las variables de entorno.

    services:
      app:
        # La definición del servicio app
      mysql:
        image: mysql:8.0
        volumes:
          - todo-mysql-data:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: secret
          MYSQL_DATABASE: todos
    
    volumes:
      todo-mysql-data:

En este punto, tu archivo compose.yaml completo debería verse así:

services:
  app:
    image: node:24-alpine
    command: sh -c "npm install && npm run dev"
    ports:
      - 127.0.0.1:3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

  mysql:
    image: mysql:8.0
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

Ejecutar la pila de la aplicación

Ahora que tienes tu archivo compose.yaml, puedes iniciar tu aplicación.

  1. Asegúrate primero de que no se estén ejecutando otras copias de los contenedores. Utiliza docker ps para enumerar los contenedores y docker rm -f <ids> para eliminarlos.

  2. Inicia la pila de la aplicación utilizando el comando docker compose up. Agrega la bandera -d para ejecutar todo en segundo plano.

    $ docker compose up -d
    

    Al ejecutar el comando anterior, deberías ver una salida como la siguiente:

    Creating network "app_default" with the default driver
    Creating volume "app_todo-mysql-data" with default driver
    Creating app_app_1   ... done
    Creating app_mysql_1 ... done

    Notarás que Docker Compose creó el volumen así como una red. Por defecto, Docker Compose crea automáticamente una red específicamente para la pila de la aplicación (que es la razón por la que no definiste una en el archivo de Compose).

  3. Observa los registros utilizando el comando docker compose logs -f. Verás los registros de cada uno de los servicios intercalados en una sola transmisión. Esto es increíblemente útil cuando deseas vigilar problemas relacionados con la sincronización. La bandera -f sigue el registro, por lo que te dará la salida en vivo a medida que se genera.

    Si ya ejecutaste el comando, verás una salida que se parece a esto:

    mysql_1  | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
    mysql_1  | Version: '8.0.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
    app_1    | Connected to mysql db at host mysql
    app_1    | Listening on port 3000

    El nombre del servicio se muestra al principio de la línea (a menudo en color) para ayudar a distinguir los mensajes. Si deseas ver los registros de un servicio específico, puedes agregar el nombre del servicio al final del comando de registros (por ejemplo, docker compose logs -f app).

  4. En este punto, deberías poder abrir tu aplicación en tu navegador en http://localhost:3000 y verla ejecutándose.

Ver la pila de la aplicación en el panel de control de Docker Desktop

Si miras el panel de control (Dashboard) de Docker Desktop, verás que hay un grupo llamado getting-started-app. Este es el nombre del proyecto de Docker Compose y se utiliza para agrupar los contenedores. Por defecto, el nombre del proyecto es simplemente el nombre del directorio en el que se encontraba el archivo compose.yaml.

Si expandes la pila, verás los dos contenedores que definiste en el archivo de Compose. Los nombres también son un poco más descriptivos, ya que siguen el patrón de <nombre-servicio>-<numero-replica>. Por lo tanto, es muy fácil ver rápidamente qué contenedor es tu aplicación y qué contenedor es la base de datos MySQL.

Destruir todo

Cuando estés listo para destruirlo todo, simplemente ejecuta docker compose down o presiona el ícono de la papelera en el panel de control de Docker Desktop para toda la aplicación. Los contenedores se detendrán y la red se eliminará.

Warning

Por defecto, los volúmenes con nombre en tu archivo de Compose no se eliminan al ejecutar docker compose down. Si deseas eliminar los volúmenes, debes agregar la bandera --volumes.

El panel de control de Docker Desktop no elimina los volúmenes cuando borras la pila de la aplicación.

Resumen

En esta sección, aprendiste sobre Docker Compose y cómo te ayuda a simplificar la forma en que defines y compartes aplicaciones multiservicio.

Información relacionada:

Siguientes pasos

A continuación, aprenderás sobre algunas de las mejores prácticas que puedes utilizar para mejorar tu Dockerfile.

Mejores prácticas para la compilación de imágenes ext="Image-building best practices" url="09_image_best.md" >}}