🇺🇸 EN
Cloud
·8 min read·↗·🇺🇸 EN

Guía paso a paso para aprender Docker Compose

Portada principal del artículo: Guía paso a paso para aprender Docker Compose

Si trabajas con Docker, escribir comandos para cada acción no es nada práctico, y a veces puede convertirse en una pesadilla cuando un error tipográfico rompe el proceso y te obliga a ejecutar todo de nuevo.

Hoy aprenderemos cómo Docker Compose hace que nuestra experiencia con Docker sea fácil y entretenida.

El contenido de este artículo incluye:

  • ¿Por qué usar Docker Compose?

  • Cómo crear un archivo docker-compose.yml.

  • Automatizar la construcción de imágenes y variables de entorno.

  • Orquestar y comunicar contenedores con Docker Compose (agregando puertos, volúmenes y redes).

  • Solución de problemas con logs de contenedores y acceso a la shell.

La idea es mover todos nuestros comandos y tareas cotidianas desde la terminal de Docker hacia Docker Compose usando un archivo docker-compose.yml, acelerando nuestra productividad.

Si todavía no estás familiarizado con Docker, te invito a leer mi artículo anterior sobre Docker desde cero para sobrevivir.

¿Por qué usar Docker Compose?

Hoy en día, la mayoría de nuestras aplicaciones no funcionan solas. Necesitan una base de datos, un servicio de almacenamiento, una API de autenticación y otros servicios a su alrededor, donde cada uno debe convertirse en un contenedor.

Docker Compose nos simplifica la vida: realiza todo con un solo comando, ayuda a compilar imágenes y orquesta nuestros contenedores.

En resumen, Docker Compose se encarga del ciclo de vida de la aplicación y nos permite gestionar acciones de los contenedores como iniciar, detener, consultar su estado, publicar puertos y comunicarlos entre redes.

El comando docker-compose cuenta con tres opciones esenciales:

  • docker-compose build: Compila los contenedores definidos en el archivo docker-compose.yml.

  • docker-compose up: Inicia los contenedores y las redes.

  • docker-compose down: Detiene los contenedores y las redes.

Toda la configuración funciona gracias al archivo docker-compose.yml que está detrás, así que vamos a hablar de él.

El archivo docker-compose.yml

Al igual que con el Dockerfile, usamos el archivo docker-compose.yml, el cual tiene dos áreas principales: la versión, que define el esquema soportado, y los servicios (services), que representan las definiciones de nuestros contenedores.

La sección de servicios es el lugar donde definimos nuestros contenedores. Soporta propiedades adicionales como image, build, environment, volumes, ports, networks y más.

En los archivos YML, la indentación es fundamental y siempre debes usar espacios.

Tenemos la forma tradicional con Docker y la forma con Docker Compose: la primera requiere escribir comandos largos en la terminal, mientras que la segunda consiste en declarar la configuración dentro del archivo docker-compose.yml.

Crea un archivo docker-compose.yml con dos propiedades: version y services.

  • version: le indicamos a Docker qué versión del esquema vamos a usar.

  • services: declara el contenedor web. Además, agregamos la propiedad image con el valor nginx.

version: '3.0'
services:
  web:
    image: nginx

Guarda el archivo y ejecuta el comando docker-compose up para compilar, crear e iniciar el contenedor.

dany@dany:~/Documents/docker-learn$ docker-compose up
Building with the native build. Learn about the native build in Compose here: https://docs.docker.com/go/compose-native-build/
Creating docker-learn_web_1 ... done
Attaching to docker-learn_web_1
web_1  | Starting up HTTP-server, serving ./

Docker Compose termina el proceso y muestra la salida directamente en la terminal.

Comandos de Docker Compose

Tenemos más opciones para iniciar, detener y monitorear nuestros contenedores.

Docker Compose acepta los siguientes parámetros:

start: Inicia contenedores sin vincularse a la terminal.

docker-compose start

start -d: Inicia un contenedor específico y se desconecta de la terminal usando la bandera -d.

docker-compose up  -d web

--no-deps nombre_del_contenedor: Inicia un contenedor específico sin levantar sus dependencias.

docker-compose up --no-deps web

ps: Muestra los contenedores activos.

docker-compose ps

stop: Detiene los contenedores.

docker-compose stop

Puertos

Con nuestras imágenes listas, el siguiente paso es declarar puertos para acceder a los contenedores. De la forma tradicional con Docker, escribimos:

 docker run -p 80:80 imagename

En Docker Compose, agregamos la propiedad ports, por ejemplo:

  ports:
    - "3000:3000"

Volúmenes

Para guardar datos de nuestro contenedor en nuestra máquina local, usamos volúmenes. Con Docker tradicional escribimos:

docker run -v $(PWD):/var/www imagename

En Docker Compose, agregamos una nueva propiedad volumes indicando el directorio del host y la ruta del contenedor:

  volumes:
   -./logs: var/www/logs

Variables de entorno

Para declarar una variable de entorno de la forma tradicional con Docker, escribimos:

docker run --env NODE_ENV=production imagename

En Docker Compose, agregamos la propiedad environment con la lista de todas las variables:

  environment:
    - NODE_ENV=production
    - APP_VERSION: 1.0

O también podemos cargarlas desde un archivo externo:

env_file 
  - ./settings.env
  - ./app.env

Redes bridge

Necesitamos una red para comunicar aplicaciones, APIs o bases de datos. Una red de tipo bridge permite la comunicación entre contenedores.

De la forma tradicional con Docker escribimos:

docker network create --driver bridge network name

En Docker Compose, agregamos la clave networks con el nombre y el tipo de driver:

networks:
      danynetwork:
        driver: bridge

Usar variables de entorno

En la mayoría de los escenarios, queremos tener contenedores para producción y para desarrollo. Podemos indicarle a Docker Compose qué compilación usar para cada entorno mediante variables de entorno.

Primero, definimos nuestra variable de entorno en la máquina en Linux o Mac usando export:

export WEB_ENV=dev
export WEB_ENV= prod

En una máquina Windows con PowerShell: bash $env:WEB_ENV = "dev". El siguiente paso es crear dos archivos Dockerfile con los nombres web.dev.dockerfile y web.prod.dockerfile.

El archivo web.dev.dockerfile usa un servidor HTTP en modo desarrollo:

FROM        node:alpine
LABEL       author=" Dany  Paredes"
WORKDIR     /var/www
COPY        src/index.html  .
RUN         npm  install  http-server  -g
EXPOSE      8080
ENTRYPOINT  ["http-server"]

El archivo web.prod.dockerfile usa nginx: yml FROM nginx LABEL author="Production" WORKDIR /usr/share/nginx/HTML COPY src/index.html . EXPOSE 80. Luego editamos el archivo docker-compose.yml en el servicio: eliminamos la clave image y agregamos la opción build para indicar el contexto y el nombre del Dockerfile.

El nombre del Dockerfile utiliza interpolación con nuestra variable de entorno, como web.${WEB_ENV}.dockerfile, y toma el valor correspondiente, por ejemplo, dev.

version: '3.0'
services:
  web:
    build:
      context: .
      dockerfile: web.${WEB_ENV}.dockerfile
networks:
  danynetwork:
    driver: bridge

Docker Compose toma la variable de entorno WEB_ENV durante el proceso de compilación y reemplaza el valor con el entorno configurado.

En la terminal, ejecutamos docker-compose build. Esto creará nuestros contenedores utilizando el entorno de desarrollo:

docker-compose build
Sending build context to Docker daemon  47.62kB
Successfully built f68d5cded665
Successfully tagged docker-learn_web:latest

También podemos usar las variables de entorno en el proceso de publicación hacia Docker Hub.

Publicar en Docker Hub

Si recuerdas el proceso para publicar nuestras imágenes en Docker Hub, necesitamos indicar el usuario de Docker Hub y el nombre de la imagen.

De la forma tradicional con Docker: bash docker push dockerhubusername/imagename. Con Docker Compose, declaramos otra variable de entorno para el usuario de Docker Hub, como DOCKERHUBUSER:

export DOCKERHUBUSER=danywalls

Editamos el archivo docker-compose.yml y agregamos la propiedad image con ${DOCKERHUBUSER} como parte del nombre de la imagen:

version: '3.0'
services:
  web:
    image: ${DOCKERHUBUSER}/web
    build:
      context: .
      dockerfile: web.${WEB_ENV}.dockerfile
    networks:
      - danynetwork
networks:
  danynetwork:
    driver: bridge

A continuación, ejecutamos docker-compose push. Esto publica automáticamente nuestra imagen en Docker Hub:

dany@dany:~/Documents/docker-learn$ docker-compose push
Pushing web (danywalls/web:latest)...
The push refers to repository [docker.io/danywalls/web]
latest: digest: sha256:c4ac44d2e318200eeafb03cdb7e64bc60d0da52092de5bacd69e2e9de10402c0 size: 1783

Solución de problemas en contenedores

A veces los contenedores fallan o necesitamos consultar los logs.

De la forma tradicional con Docker, necesitamos escribir el ID del contenedor: bash docker logs myid. En Docker Compose, aprovechamos el contexto de ejecución para mostrar los logs de todos los servicios declarados en el archivo docker-compose.yml:

docker-compose logs

O también podemos elegir un contenedor específico usando su nombre: bash docker-compose logs web. Y si queremos leer las últimas cinco líneas del log: docker-compose logs --tail=5.

Acceder a la shell de un contenedor

A veces necesitamos acceder al contenedor para listar archivos o navegar dentro de él.

De la forma tradicional con Docker:
bash docker exec it container id sh. Con Docker Compose es muy similar, usando el nombre del servicio:

docker-compose exec web sh

Resumen

Aprendimos cómo usar Docker Compose para orquestar contenedores y declarar puertos, volúmenes, variables de entorno y redes directamente en nuestros archivos de configuración.

También vimos cómo consultar logs y usar comandos de Docker Compose para iniciar, detener o listar contenedores.

Trabajar con Docker Compose simplifica nuestras tareas diarias con Docker porque tenemos todo el contexto de ejecución y de los contenedores en un solo lugar.

Foto de frank mckenna en Unsplash

Foto de David Clode en Unsplash

Parte de la serie Cloud

Explora más guías prácticas y arquitecturas reales en la serie Cloud.

Ver serie completa

Artículos Relacionados

Compartir este artículo

Si esta guía te resultó útil, compártela con tu equipo o con otros desarrolladores.


Software real. Lecciones reales.

Comparto las lecciones que aprendí por las malas, para que puedas evitarlas o estar preparado cuando ocurran.

User avatar
User avatar
User avatar
User avatar
+13K

Únete a 13,800+ desarrolladores y lectores.

Cero spam. Cancela tu suscripción en cualquier momento.