Docker Compose

Author
Por Darío Rivera
Publicado el en Docker

Docker Compose es una herramienta usada para definir y administrar aplicaciones de multi-contenedor con Docker. Es bastante útil cuando se tiene varios servicios como apache, mysql, redis ya que se puede crear diferentes contenedores para cada servicio.

Para usa Docker Compose, debes instalar el paquete necesario en tu distribución de Linux preferida con tu sistema de gestión de paquetes. Enseguida, podrás crear y definir tus contenedores utilizando el archivo docker-compose.yml.

Vamos a iniciar con un ejemplo muy sencillo.

version: '3.9'

services:
  web:
    image: nginx:latest

En este primer ejemplo hemos creado un docker compose file muy sencillo el cual define un servicio. Veamos que significa cada uno de los elementos.

version
Define la versión del formato de archivo de Docker Compose.
services
Inicia la definición de los servicios que formarán parte de nuestra aplicación. Cada servicio creará un contenedor.
web
Define un servicio llamado "web". Este nombre es totalmente personalizado. Hubiera podido ser "apache" o "server".
image
Especifica que queremos usar la imagen más reciente de nginx.

Veamos el siguiente ejemplo basado en el anterior en donde hemos agregado un servicio adicional para base de datos.

version: '3.9'

services:
  web:
    image: nginx:latest

  database:
    image: mysql:5.7

Por defecto, todos los servicios creados en el archivo docker compose comparten la misma red, es decir, que se pueden comunicar uno con otro sin necesidad de una configuración adicional. El nombre de host porspuesto, será el nombre del servicio.

Contexto

El "contexto" en Docker y Docker Compose se refiere generalmente al contexto de construcción cuando estamos tratando con la creación de imágenes Docker a partir de un Dockerfile. Supongamos que queremos personalizar un poco la imagen inicial de ngnix para agregar algunas cosas, entonces debemos crear un archivo Dockerfile. En este caso, lo hemos creado en el mismo directorio de nuestro docker-compose.yml.

docker-compose.yml

version: '3.9'

services:
  web:
    build: .

  database:
    image: mysql:5.7

Dockerfile

FROM nginx:latest

De esta forma nuestro servicio llamado "web" estaría utilizando el Dockerfile en el directorio actual para construir el servicio. El anterior archivo muestra la forma abreviada de especificar el contexto de construcción del servicio. Podríamos utilizar la forma extensa de la siguiente forma y sería equivalente:

version: '3.9'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile

  database:
    image: mysql:5.7

La forma extensa es útil si necesitas crear una configuración mucho más compleja, generalmente con archivos de configuración adicionales para tu servicio. No es necesario que especifiques el key dockerfile a menos que quieras que el nombre de tu archivo de docker sea diferente de "Dockerfile".

Supongamos que queremos agregar una configuración al servidor de nginx, podríamos crear una carpeta llamada "web" para guardar todo lo relacionado con el servicio llamado también web. La estructura de directorios sería la siguiente. Nota que el archivo Dockerfile ahora está en web/Dockerfile.

mi_proyecto/
|-- docker-compose.yml
|-- web/
    |-- Dockerfile
    |-- nginx.conf
    |-- my_custom_config.conf

Nuestra configuración ahora sería:

version: '3.9'

services:
  web:
    build:
      context: web

  database:
    image: mysql:5.7

Finalmente, el Dockerfile podría quedar como sigue copiando la configuración respectiva al directorio de nginx.

FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf
COPY my_custom_config.conf /etc/nginx/conf.d/

No hemos entrado en detalles respecto a cómo serían los archivos específicos de configuración de nginx ya que no es el objetivo de este post.

Puertos

Como has de adivinar cuando se monta un servidor web se necesitan comunicación con puertos específicos como el puerto 80. En nuestra configuración de docker compose podemos configurar mediante cual puerto accederemos a nuestro servidor web.

version: '3.9'

services:
  web:
    build:
      context: web
    ports:
      - "8080:80"

  database:
    image: mysql:5.7

Agregando el elemento ports como "8080:80" podremos acceder desde nuestra máquina host al contenedor mediante el puerto 8080 ya que este puerto será redirigido al puerto 80 del contenedor. En síntesis, cuando accedamos al browser muy seguramente accederemos a 127.0.0.1:8080.

Volúmenes

Los volúmenes en Docker son mecanismos que permiten persistir y compartir datos entre el host y los contenedores. Esto es útil por ejemplo cuando queremos utilizar el código fuente de nuestro proyecto en el contenedor sin necesidad de copiarlos y crear dos versiones diferentes de cada archivo. Vamos a modificar levemente nuestro ejemplo para que toda la configuración de docker quede bajo el folder de "docker" y todo el código fuente quede en "src".

mi_proyecto/
|-- docker-compose.yml
|-- src/
|   |-- index.html
|   |-- ...
|-- docker/
    |-- web/
    |   |-- Dockerfile
    |   |-- nginx.conf
    |   |-- my_custom_config.conf

para crear un volumen que comparta el código de nuestro proyecto en "src" con el contenedor podemos hacerlo así:

version: '3.9'

services:
  web:
    build:
      context: ./docker/web
      dockerfile: Dockerfile
    ports:
      - "80:80"
    volumes:
      - ./src:/usr/share/nginx/html

Estando dentro del contenedor veremos los archivos en /usr/share/nginx/html.

Argumentos

Ya vimos que son los argumentos en nuestro post Variables de Entorno y Argumentos en Docker. Para especificar argumentos en docker compose puedes utilizar el elemento args bajo el elemento build.

version: '3.9'

services:
  web:
    build:
      context: ./docker/web
      args:
        - PHP_VERSION=8.2

Variables de Entorno

Para especificar variables de entorno en docker compose puedes utilizar el elemento enviroment bajo el elemento build. Estas variables son llamadas variables en línea.

version: '3.9'

services:
  web:
    build: .
      environment:
        - DEBUG_MODE=true

También es posible especificar un archivo de variables de entorno así:

version: '3.9'

services:
  web:
    build: .
    env_file:
      - .env.list

Finalmente es importante mencionar que docker compose tomará por defecto las variables del archivo .env (si existe) o las variables del HOST si estas son declaradas en el docker file. Para saber a más detalle cómo funcionan las variables de entorno puedes ver nuestro artículo Variables de Entorno y Argumentos en Docker.


Acerca de Darío Rivera

Author

Application Architect at Elentra Corp . Quality developer and passionate learner with 10+ years of experience in web technologies. Creator of EasyHttp , an standard way to consume HTTP Clients.

LinkedIn Twitter Instagram

Sólo aquellos que han alcanzado el éxito saben que siempre estuvo a un paso del momento en que pensaron renunciar.