Docker Compose

Introducción a Compose

Compose es una herramienta para definir y ejecutar aplicaciones Docker de múltiples contenedores. Con Compose, puede usar un archivo YML para configurar todos los servicios que necesita la aplicación. Luego, usando un comando, puede crear e iniciar todos los servicios desde la configuración del archivo YML.

Si aún no comprende la configuración de archivos YML, primero puede leer elTutorial de introducción a YAML。

Tres pasos para usar Compose:

  • Use Dockerfile para definir el entorno de la aplicación.

  • Use docker-compose.yml para definir los servicios que componen la aplicación, de modo que puedan ejecutarse juntos en un entorno aislado.

  • Finalmente, ejecute el comando docker-compose up para iniciar y ejecutar toda la aplicación.

Un ejemplo de configuración de docker-compose.yml es el siguiente (consulte los parámetros de configuración a continuación):

Ejemplo

# Ejemplo de configuración yaml
version
: '3'
services
:
  web
:
    build
: .
    ports
:
   - "5000:5000"
    volumes
:
   - .:/code
    - logvolume01:/var/log
    links
:
   - redis
  redis
:
    image
: redis
volumes
:
  logvolume01
: {}

Instalación de Compose

En Linux, podemos descargar su paquete binario desde Github para usarlo. La dirección de la última versión publicada es:https://github.com/docker/compose/releases。

Ejecute el siguiente comando para descargar la versión estable actual de Docker Compose:

$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Para instalar otra versión de Compose, reemplace v2.2.2.

Docker Compose está alojado en GitHub, no es muy estable.

También puede instalar Docker Compose rápidamente ejecutando el siguiente comando.

curl -L https://get.daocloud.io/docker/compose/releases/download/v2.4.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

Aplique permisos de ejecución al archivo binario:

$ sudo chmod +x /usr/local/bin/docker-compose

Cree un enlace simbólico:

$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

Pruebe si la instalación se realizó correctamente:

$ docker-compose version
cker-compose version 1.24.1, build 4667896b

Nota: Para alpine, se necesitan los siguientes paquetes de dependencias: py-pip, python-dev, libffi-dev, openssl-dev, gcc, libc-dev y make.

macOS

Docker Desktop para Mac y Docker Toolbox ya incluyen Compose y otras aplicaciones Docker, por lo que los usuarios de Mac no necesitan instalar Compose por separado. Puede consultar las instrucciones de instalación de Docker enInstalación de Docker en MacOS。

windows PC

Docker Desktop para Windows y Docker Toolbox ya incluyen Compose y otras aplicaciones Docker, por lo que los usuarios de Windows no necesitan instalar Compose por separado. Puede consultar las instrucciones de instalación de Docker enInstalación de Docker en Windows。


Uso

1. Preparación

Cree un directorio de prueba:

$ mkdir composetest
$ cd composetest

Cree un archivo llamado app.py en el directorio de prueba y copie y pegue el siguiente contenido:

Código del archivo composetest/app.py

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 have been seen {} times.\n'.format(count)

En este ejemplo, redis es el nombre de host del contenedor redis en la red de la aplicación, y ese host usa el puerto 6379.

En el directorio composetest, cree otro archivo llamadorequirements.txtcon el siguiente contenido:

flask
redis

2. Crear el archivo Dockerfile

En el directorio composetest, cree un archivo llamadoDockerfilecon el siguiente contenido:

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
COPY . .
CMD ["flask", "run"]

Explicación del contenido de Dockerfile:

  • FROM python:3.7-alpine: Construye la imagen a partir de la imagen Python 3.7.
  • WORKDIR /code: Establece el directorio de trabajo en /code.
  • ENV FLASK_APP app.py
    ENV FLASK_RUN_HOST 0.0.0.0

    Configura las variables de entorno utilizadas por el comando flask.

  • RUN apk add --no-cache gcc musl-dev linux-headers: Instala gcc para que los paquetes de Python, como MarkupSafe y SQLAlchemy, puedan compilarse y acelerarse.
  • COPY requirements.txt requirements.txt
    RUN pip install -r requirements.txt

    Copia requirements.txt e instala las dependencias de Python.

  • COPY . .: Copia el directorio actual del proyecto al directorio de trabajo de la imagen.
  • CMD ["flask", "run"]: Proporciona el comando de ejecución predeterminado para el contenedor: flask run.

3. Crear docker-compose.yml

En el directorio de prueba, cree un archivo llamado docker-compose.yml y pegue el siguiente contenido:

Archivo de configuración docker-compose.yml

# Configuración yaml
version
: '3'
services
:
  web
:
    build
: .
    ports
:
     - "5000:5000"
  redis
:
    image
: "redis:alpine"

Este archivo Compose define dos servicios: web y redis.

  • web: El servicio web usa la imagen construida desde el Dockerfile en el directorio actual. Luego, vincula el contenedor y el host al puerto expuesto 5000. Este servicio de ejemplo usa el puerto predeterminado 5000 del servidor web Flask.
  • redis: El servicio redis utiliza la imagen pública de Redis de Docker Hub.

4. Construir y ejecutar su aplicación con comandos de Compose

En el directorio de prueba, ejecute el siguiente comando para iniciar la aplicación:

docker-compose up

Si desea ejecutar el servicio en segundo plano, puede agregar el-dparámetro:

docker-compose up -d

Referencia de directivas de configuración de yml

version

Especifica la versión de Compose a la que se ajusta este yml.

build

Especifica la ruta de contexto para construir la imagen:

Por ejemplo, para el servicio webapp, especifica la imagen construida desde la ruta de contexto ./dir/Dockerfile:

version: "3.7"
services:
  webapp:
    build: ./dir

O bien, como un objeto con la ruta especificada en el contexto, y Dockerfile y args opcionales:

version: "3.7"
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1
      labels:
        - "com.example.description=Accounting webapp"
        - "com.example.department=Finance"
        - "com.example.label-with-empty-value"
      target: prod
  • context: ruta de contexto.
  • dockerfile: especifica el nombre del archivo Dockerfile para construir la imagen.
  • args: agrega argumentos de construcción, que son variables de entorno a las que solo se puede acceder durante el proceso de construcción.
  • labels: establece las etiquetas de la imagen construida.
  • target: en construcciones de múltiples etapas, permite especificar qué etapa construir.

cap_add,cap_drop

Agrega o elimina las capacidades del núcleo del host que tiene el contenedor.

cap_add:
  - ALL # 开启全部权限

cap_drop:
  - SYS_PTRACE # 关闭 ptrace权限

cgroup_parent

Especifica el grupo cgroup padre para el contenedor, lo que significa que heredará las limitaciones de recursos de ese grupo.

cgroup_parent: m-executor-abcd

command

Sobrescribe el comando predeterminado para iniciar el contenedor.

command: ["bundle", "exec", "thin", "-p", "3000"]

container_name

Especifica un nombre de contenedor personalizado, en lugar del nombre predeterminado generado.

container_name: my-web-container

depends_on

Establece dependencias.

  • docker-compose up : inicia los servicios en orden de dependencia. En el siguiente ejemplo, se inician primero db y redis, y luego se inicia web.
  • docker-compose up SERVICE: incluye automáticamente las dependencias de SERVICE. En el siguiente ejemplo, docker-compose up web también creará e iniciará db y redis.
  • docker-compose stop : detiene los servicios en orden de dependencia. En el siguiente ejemplo, web se detiene antes que db y redis.
version: "3.7"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

Nota: el servicio web no espera a que redis db se inicie por completo antes de iniciarse.

deploy

Especifica la configuración relacionada con la implementación y ejecución del servicio. Solo es útil en modo swarm.

version: "3.7"
services:
  redis:
    image: redis:alpine
    deploy:
      mode:replicated
      replicas: 6
      endpoint_mode: dnsrr
      labels: 
        description: "This redis service label"
      resources:
        limits:
          cpus: '0.50'
          memory: 50M
        reservations:
          cpus: '0.25'
          memory: 20M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s

Parámetros opcionales:

endpoint_mode: Modo de acceso a los servicios del clúster.

endpoint_mode: vip 
# Docker 集群服务一个对外的虚拟 ip。所有的请求都会通过这个虚拟 ip 到达集群服务内部的机器。
endpoint_mode: dnsrr
# DNS 轮询(DNSRR)。所有的请求会自动轮询获取到集群 ip 列表中的一个 ip 地址。

labels: Establece etiquetas en el servicio. Las etiquetas del contenedor (configuración al mismo nivel que deploy) pueden sobrescribir las etiquetas bajo deploy.

mode: Especifica el modo que ofrece el servicio.

  • replicated: Modo replicado, replica el servicio especificado en las máquinas del clúster.

  • global: Modo global, el servicio se implementará en cada nodo del clúster.

  • Diagrama: en la siguiente figura, los bloques amarillos muestran el funcionamiento del modo replicated, y los bloques grises muestran el funcionamiento del modo global.

replicas:modeCuando se usa replicated, se necesita este parámetro para configurar el número específico de nodos en ejecución.

resources: Configura los límites de uso de recursos del servidor. Por ejemplo, en el caso anterior, configura el porcentaje de CPU y la ocupación de memoria necesarios para que el clúster redis se ejecute. Evita que el uso excesivo de recursos cause anomalías.

restart_policy: Configura cómo reiniciar el contenedor cuando este sale.

  • condition: puede ser none, on-failure o any (valor predeterminado: any).
  • delay: establece cuánto tiempo después se reinicia (valor predeterminado: 0).
  • max_attempts: número de intentos de reiniciar el contenedor; si se supera, ya no se intenta (valor predeterminado: reintentar siempre).
  • window: establece el tiempo de espera para reiniciar el contenedor (valor predeterminado: 0).

rollback_config: Configura cómo debe realizarse el rollback del servicio en caso de que la actualización falle.

  • parallelism: número de contenedores a revertir a la vez. Si se establece en 0, todos los contenedores se revertirán simultáneamente.
  • delay: tiempo de espera entre cada grupo de contenedores durante el rollback (por defecto 0s).
  • failure_action: qué hacer si falla el rollback. Uno de continue o pause (por defecto pause).
  • monitor: tiempo durante el cual se observa continuamente si hay fallos después de cada actualización de contenedor (ns|us|ms|s|m|h) (por defecto 0s).
  • max_failure_ratio: proporción de fallos tolerable durante el rollback (por defecto 0).
  • order: orden de operaciones durante el rollback. Uno de stop-first (rollback en serie) o start-first (rollback en paralelo) (por defecto stop-first).

update_config: Configura cómo debe actualizarse el servicio, útil para actualizaciones progresivas (rolling updates).

  • parallelism: número de contenedores a actualizar a la vez.
  • delay: tiempo de espera entre la actualización de un grupo de contenedores.
  • failure_action: qué hacer si falla la actualización. Uno de continue, rollback o pause (por defecto: pause).
  • monitor: tiempo durante el cual se observa continuamente si hay fallos después de cada actualización de contenedor (ns|us|ms|s|m|h) (por defecto 0s).
  • max_failure_ratio: proporción de fallos tolerable durante el proceso de actualización.
  • order: orden de operaciones durante el rollback. Uno de stop-first (rollback en serie) o start-first (rollback en paralelo) (por defecto stop-first).

Nota.: Solo compatible con V3.4 y versiones posteriores.

devices

Especifica la lista de asignación de dispositivos.

devices:
  - "/dev/ttyUSB0:/dev/ttyUSB0"

dns

Servidores DNS personalizados, pueden ser un único valor o una lista de varios valores.

dns: 8.8.8.8

dns:
  - 8.8.8.8
  - 9.9.9.9

dns_search

Dominios de búsqueda DNS personalizados. Pueden ser un único valor o una lista.

dns_search: example.com

dns_search:
  - dc1.example.com
  - dc2.example.com

entrypoint

Sobrescribe el entrypoint predeterminado del contenedor.

entrypoint: /code/entrypoint.sh

También puede tener el siguiente formato:

entrypoint:
    - php
    - -d
    - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
    - -d
    - memory_limit=-1
    - vendor/bin/phpunit

env_file

Añadir variables de entorno desde un archivo. Puede ser un único valor o una lista de varios valores.

env_file: .env

También puede estar en formato de lista:

env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env

environment

Añadir variables de entorno. Puede usar arrays o diccionarios; cualquier valor booleano debe ir entre comillas para asegurar que el analizador YML no lo convierta en True o False.

environment:
  RACK_ENV: development
  SHOW: 'true'

expose

Expone puertos, pero no los mapea al host; solo son accesibles por los servicios conectados.

Solo se puede especificar el puerto interno como parámetro:

expose:
 - "3000"
 - "8000"

extra_hosts

Añadir asignaciones de nombre de host. Similar a docker client --add-host.

extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"

Lo anterior creará una asignación con dirección IP y nombre de host en /etc/hosts dentro del contenedor de este servicio:

162.242.195.82  somehost
50.31.209.229   otherhost

healthcheck

Se utiliza para detectar si el servicio de Docker se está ejecutando de forma saludable.

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
  interval: 1m30s # 设置检测间隔
  timeout: 10s # 设置检测超时时间
  retries: 3 # 设置重试次数
  start_period: 40s # 启动后,多少秒开始启动检测程序

image

Especifica la imagen que ejecuta el contenedor. Los siguientes formatos son válidos:

image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像id

logging

Configuración del registro de logs del servicio.

driver: especifica el controlador de registro para los contenedores del servicio, el valor predeterminado es json-file. Hay las siguientes tres opciones:

driver: "json-file"
driver: "syslog"
driver: "none"

Solo con el controlador json-file se pueden usar los siguientes parámetros para limitar la cantidad y el tamaño de los logs.

logging:
  driver: json-file
  options:
    max-size: "200k" # 单个文件大小为200k
    max-file: "10" # 最多10个文件

Cuando se alcanza el límite máximo de archivos, los archivos antiguos se eliminan automáticamente.

Con el controlador syslog, se puede usar syslog-address para especificar la dirección de recepción de logs.

logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"

network_mode

Establece el modo de red.

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

networks

Configura las redes a las que se conecta el contenedor, haciendo referencia a las entradas bajo networks de nivel superior.

services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:
         - alias2
networks:
  some-network:
    # Use a custom driver
    driver: custom-driver-1
  other-network:
    # Use a custom driver which takes special options
    driver: custom-driver-2

aliases: Otros contenedores en la misma red pueden usar el nombre del servicio o este alias para conectarse al servicio del contenedor correspondiente.

restart

  • no: es la política de reinicio predeterminada, no reinicia el contenedor en ningún caso.
  • always: el contenedor se reinicia siempre.
  • on-failure: solo reinicia el contenedor cuando este sale de forma anormal (código de salida distinto de 0).
  • unless-stopped: reinicia siempre el contenedor cuando sale, pero no tiene en cuenta los contenedores que ya estaban detenidos cuando se inició el demonio de Docker.
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

Nota: en modo de clúster swarm, use restart_policy en su lugar.

secrets

Almacenar datos sensibles, como contraseñas:

version: "3.1"
services:

mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my_secret
  secrets:
    - my_secret

secrets:
  my_secret:
    file: ./my_secret.txt

security_opt

Modifica la etiqueta de esquema predeterminada del contenedor.

security-opt:
  - label:user:USER   # 设置容器的用户标签
  - label:role:ROLE   # 设置容器的角色标签
  - label:type:TYPE   # 设置容器的安全策略标签
  - label:level:LEVEL  # 设置容器的安全等级标签

stop_grace_period

Especifica cuánto tiempo esperar antes de enviar la señal SIGKILL para cerrar el contenedor si este no puede manejar SIGTERM (o cualquier señal de stop_signal).

stop_grace_period: 1s # 等待 1 秒
stop_grace_period: 1m30s # 等待 1 分 30 秒 

El tiempo de espera predeterminado es de 10 segundos.

stop_signal

Establece una señal alternativa para detener el contenedor. Por defecto se usa SIGTERM.

El siguiente ejemplo usa SIGUSR1 en lugar de SIGTERM para detener el contenedor.

stop_signal: SIGUSR1

sysctls

Establece parámetros del kernel en el contenedor; se pueden usar formatos de array o diccionario.

sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0

tmpfs

Monta un sistema de archivos temporal dentro del contenedor. Puede ser un único valor o una lista de varios valores.

tmpfs: /run

tmpfs:
  - /run
  - /tmp

ulimits

Sobrescribe el ulimit predeterminado del contenedor.

ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000

volumes

Monta volúmenes de datos o archivos del host en el contenedor.

version: "3.7"
services:
  db:
    image: postgres:latest
    volumes:
      - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
      - "/localhost/data:/var/lib/postgresql/data"
Otras extensiones.