Compose: orquestación de aplicaciones de contenedores Docker

Compose automatiza la gestión de contenedores, por lo que facilita el escalado e implementación de aplicaciones en Docker. En este tutorial, examinamos en profundidad la configuración y el uso de Docker Compose para que puedas aplicarlo en tu propio entorno de producción.

¿Qué es Docker Compose?

Docker Compose se utiliza para gestionar aplicaciones y aumentar la eficiencia en el desarrollo de contenedores. La configuración se guarda en un único archivo YAML, lo que permite crear y escalar aplicaciones fácilmente. Docker Compose se utiliza a menudo para configurar un entorno local, pero también puede formar parte de un flujo de trabajo de continuous integration / continuous delivery (CI/CD). Los desarrolladores pueden definir una versión específica de contenedores para pruebas o para una fase específica del pipeline. Esto facilita la identificación de problemas y la corrección de errores antes de que pasen a producción.

Docker Compose: estos son los requisitos

Para la orquestación de contenedores necesitas tener tanto Docker Engine como Docker Compose. Por lo tanto, debes tener una de las siguientes opciones configuradas en tu sistema:

  • Docker Engine y Docker Compose: pueden instalarse como binarios independientes
  • Docker Desktop: entorno de desarrollo con interfaz gráfica de usuario que incluye Docker Engine y Docker Compose
Consejo

En nuestras guías puedes aprender a instalar Docker Compose en diferentes sistemas operativos:

Guía paso a paso: cómo utilizar Docker Compose

Para mostrarte los conceptos de Docker Compose, vamos a utilizar una sencilla aplicación web de Python que incorpora un contador de solicitudes. Para ello, se recurre al framework Python Flask y a la base de datos en memoria Redis (también conocida como In-Memory Database). No te va a hacer falta instalar Python ni Redis, ya que dispondrás de ellos como imágenes de Docker.

Paso 1. Crear los archivos del proyecto

Abre el terminal y crea una nueva carpeta para el proyecto.

$ mkdir composedemo
shell

Luego, entra en la carpeta que acabas de crear.

$ cd composedemo
shell

Crea el archivo app.py en la carpeta e introduce el siguiente código:

import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)
@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I was here {} times.\n'.format(count)
python

Estamos utilizando “redis” como nombre de host y el puerto “6379” como puerto predeterminado. Además, hemos especificado que la función get_hit_count() debe intentar conectarse al servicio varias veces. Es lo más recomendable, ya que Redis puede no estar disponible nada más iniciar la aplicación o puede tener problemas de conexión durante su ejecución.

Crea también el archivo requirements.txt con las dependencias necesarias:

flask
redis
plaintext

Paso 2. Configurar Dockerfile

Dockerfile se utiliza para crear la imagen de Docker. Aquí es donde se especifican todas las dependencias que necesita la aplicación de Python.


FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
shell

Dockerfile está indicando a Docker que utilice la imagen Python 3.7. También hemos definido las variables de entorno para el comando flask. Con apk add estamos instalando gcc y otras dependencias. Con EXPOSE estamos indicando que el contenedor debe monitorizar el puerto 5000. Con COPY copiamos el contenido de la carpeta actual en el directorio de trabajo /code. Finalmente, hemos definido flask run como comando predeterminado para el contenedor.

Comprueba que el archivo Dockerfile se ha guardado sin extensión, ya que algunos editores añaden automáticamente el sufijo .txt.

Paso 3. Crear el archivo YAML

Configuramos los servicios “redis” y “web” en docker-compose.yml.

version: "3.9"
services:
    web:
        build: .
        ports:
            - "8000:5000"
    redis:
        image: "redis:alpine"
yaml

El servicio “web” utiliza la imagen creada por Dockerfile y conecta el contenedor con el ordenador host a través del puerto 8000, mientras que el servidor web Flask se ejecuta en el puerto 5000. Por otro lado, la imagen de Redis se obtiene directamente del repositorio oficial de Docker Hub.

Paso 4. Ejecutar la aplicación con Compose

Inicia la aplicación desde la carpeta de tu proyecto.

docker compose up
shell

Abre tu navegador y accede a http://localhost:8000 o http://127.0.0.1:8000, te valen ambas opciones.

Deberías ver el siguiente mensaje:

Aplicación Docker Compose: muestra en el navegador el número de veces que has visitado la página
Te muestra en el navegador el número de veces que has visitado la página.

Actualiza la página. El número de visitas debería aumentar de 1 en 1.

Al volver a ejecutar la aplicación Docker Compose
Se ha incrementado en 1 el número de veces que se ha visitado.

Detén la aplicación con el siguiente comando:

$ docker compose down
shell

También puedes presionar Ctrl + C en el terminal donde iniciaste la aplicación.

Paso 5. Añadir un Bind Mount

Si quieres añadir un Bind Mount al servicio web, puedes hacerlo en docker-compose.yml.

version: "3.9"
services:
    web:
        build: .
        ports:
            - "8000:5000"
        volumes:
            - .:/code
        environment:
            FLASK_DEBUG: "true"
    redis:
        image: "redis:alpine"
yaml

En la sección volumes, especificamos que la carpeta del proyecto actual se debe montar en el directorio /code dentro del contenedor. Esto te permite modificar el código sin necesidad de reconstruir la imagen. La variable de entorno FLASK_DEBUG se encarga de que flask run se ejecute en modo de depuración.

Paso 6. Reconstruir y ejecutar la aplicación

Introduce el siguiente comando en el terminal para reconstruir el archivo Compose:

docker compose up
shell

Paso 7. Actualizar la aplicación

Ahora que estás utilizando un Bind Mount para tu aplicación, puedes modificar tu código y ver los cambios de forma automática sin tener que reconstruir la imagen.

Agrega una nueva línea de saludo en app.py.

return 'Hello from Docker! I was here {} times.\n'.format(count)
python

Actualiza el navegador para comprobar si se han adoptado los cambios correctamente.

Aplicación Docker Compose: texto de bienvenida modificado
Se ha modificado el texto de bienvenida de la aplicación Python.

Paso 8. Otros comandos

La opción --help te muestra una lista de comandos disponibles para Docker Compose:

docker compose --help
shell

Puedes añadir el argumento -d para ejecutar Docker Compose en un segundo plano:

docker compose up -d
shell

Con down se eliminan todos los contenedores. La opción --volumes también elimina los volúmenes utilizados por el contenedor Redis.

docker compose down --volumes
shell
Consejo

Si es la primera vez que utilizas Docker, te recomendamos que consultes nuestro tutorial de Docker y un resumen general de los comandos de Docker en la Digital Guide.