524 - Cuatro Docker para emails, backup y mas

524 - Cuatro Docker para emails, backup y mas

Descubre cómo optimizar tu flujo de trabajo en #linux con cuatro contenedores #docker versátiles. Desde recibir notificaciones hasta #backup

1:25
-3:15

Con esto de la migración de Mattermost a Matrix, he tenido que implementar y actualizar algunos de los servicios y contenedores Docker que estaba utilizando. Lo cierto es que ha sido algo realmente emocionante, porque lo he hecho a contrarreloj, y en condiciones de presión y temperatura no convencionales. Tengo claro que estas herramientas son una primera aproximación y tienen margen de mejora, pero es muy probable que le puedas sacar partido alguna de ellas. O incluso modificar alguna para que te sean de utilidad.

Como te he comentado en otras ocasiones, cualquier idea, sugerencia, comentario, que quieras hacerme es siempre bienvenido. Y si es para mejorar o para añadir nuevas características a estas aplicaciones todavía mas.

Cuatro contenedores Docker para reenvío de emails, notificaciones y backup

MatrixMail

Este primer contenedor lo monté para estar al tanto de lo que me llega mi correo electrónico sin necesidad de entrar en el, y además tener agrupado todo la información de atareao.es, en un único punto.

No es nada del otro mundo. Se trata de un servicio que cada cinco minutos, aunque esto es configurable, se conecta a tu servidor de correo, y mira si tienes algún correo nuevo.

Si tienes nuevo correo, te lo envía a Matrix, y lo marca como leído. Sencillo, pero efectivo. De esta forma no es necesario que me conecte al servidor de correo.

El docker-compose.yml,

version: "3.7"

services:
  matrixmail:
    image: atareao/matrixmail:latest
    container_name: matrixmail
    init: true
    restart: unless-stopped
    volumes:
      - ./config.yml:/app/config.yml

Y una configuración de ejemplo, para el archivo config.yml,

log_level: debug
pull_time: 300
imap_server:
  host: mail.tuservidor.es
  port: 993
  user: xxxxxxxxxx
  password: "xxxxxxxxxxxx"
matrix_client:
  url: matrix.tuservidor.es
  token: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
  room: "xxxxxxxxxxxxxxxxxxxxxxxxx"

HookBridge

Este segundo contenedor es para resolver un problema con el que me encontré cuando intentaba enviar mensajes desde WatchTower a Matrix. Por alguna razón no lo conseguía enviar, y sigo, por el momento sin conseguirlo. No tengo muy claro, si es un problema de shoutrrr o que… La cuestión es que quería tener esta información y no sabía como hacerlo, así que he montado un servicio puente.

En este caso lo que haces es declarar tantos destinos, destinations, como necesites. Cada uno de estos destinos, tiene una configuración para el servicio que utiliza. Por ejemplo, Matrix, ZincObserve o Telegram.

Una vez levantado el contenedor, simplemente tienes que hacer una llamada POST, de la siguiente forma,

curl -XPOST -H "Content-Type: application/json" localhost:6969/matrix_watchtower -d '{"message": "ejemplo"}'

Si te fijas matrix_watchtower es el destino que has definido en la configuración, y el mensaje se lo pasas directamente en el cuerpo.

Así, el archivo docker-compose.yml, tendría un aspecto similar al que te comparto,

version: "3.7"

services:
  hookbridge:
    image: atareao/hookbridge:latest
    container_name: hookbridge
    init: true
    restart: unless-stopped
    volumes:
      - ./config.yml:/app/config.yml

Y la configuración sería algo como lo que ves en el siguiente config.toml,

port: 6969
log_level: debug
destinations:
  - name: matrix_watchtower
    service:
      service_type: matrix
      config:
        url: matrix.tuservidor.es
        token: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
        room: "!xxxxxxxxxxxxxxxxxxx"
  - name: zincobserve_docker
    service:
      service_type: zinc_observe
      config:
        url: https://zincobserve.tuservidor.es
        token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        index: docker
  - name: telegram_atareao_publicaciones
    service:
      service_type: telegram
      config:
        url: https://api.telegram.org
        token:
        chat_id:
        topic_id:

Esto simplifica mucho la operativa, porque los credenciales los pasas en este docker y de esta manera, te puedes abstraer de otros servicios.

DockerBoard

Este es el hermano mayor de Board. Se trata de simplificar considerablemente la configuración, y sobre todo de intentar tener mas información directamente en el tablero partiendo del socket de Docker. El resto va por etiquetas.

Este funcionamiento es similar al de Traefik o al de Caddy. Tiene la ventaja de que no tienes que reiniciar el tablero cuando añades un nuevo contenedor, si no que esto se hace de forma completamente dinámica… aunque te advierto que todavía esta parte no está integrada.

Ahora mismo lo que si que está integrado es la carga de etiquetas. En el archivo de configuración tienes que definir todas las categorías que quieras utilizar, y en el contenedor en cuestión mediante etiquetas defines que es lo que quieres que se vea y como queires que se vea. Por ejemplo,

version: "3.7"

services:
  rabbitmq:
    image: rabbitmq:3-management
    container_name: rabbitmq
    init: true
    ports:
      - 9090:15672
      - 5672:5672
    environment:
      - RABBITMQ_DEFAULT_USER=guest
      - RABBITMQ_DEFAULT_PASS=guest
    volumes:
      - rabbitmq:/var/lib/rabbitmq/mnseia/
    labels:
      es.atareao.board.active: true
      es.atareao.board.name: Rabbitmq
      es.atareao.board.description: |
        Este es un claro funcionamiento de como tiene que funcionar
        esta magnífico tablero. Con esta primera aplicación, Rabbitmq, es con
        la que me quiero lucir
      es.atareao.board.category: Category1
      es.atareao.board.url: http://localhost:9090
      es.atareao.board.icon: fa-solid fa-code-pull-request
      es.atareao.board.new_tab: true

volumes:
  rabbitmq: {}

Esto, evidentemente, lo tienes que hacer para cada uno de los contenedores que quieras que aparezcan en tu Dashboard.

Inicialmente esto puede parecerte engorroso, algo que también me pasaba inicialmente con Traefik. Sin embargo, solo tienes que ver las ventajas que ofrece. Yo para el aso de Traefik, únicamente me dedico a copiar y pegar entre docker-compose.yml, y sustituir aquello que me interesa.

La configuración del archivo config.toml, sería la siguiente,

url: https://board.sample.es
port: 6969
log_level: debug
jwt_secret: un-secreto-muy-secreto
jwt_expires_in: 60m
jwt_maxage: 60
docker_uri: unix:///run/user/1000/docker.sock
board_name: DockerBoard
users:
  - name: user1
    password: password1
    active: true
categories:
  - name: Category1
    description: Category1 description
    icon: fa-solid fa-music

Backup de Mariadb y Posgtresql

Por último, pero no menos importante, te traigo un par de contenedores, que implementé hace algún tiempo y que utilizo para hacer copias de seguridad de las bases de datos. En concreto son dos contenedores, uno para MariaDB y otro para PostgreSQL.

Actualmente lo tengo integrado con las bases de datos MariaDB de las páginas web que autoalojo. Y lo tengo hecho de forma muy sencilla. Así, en el docker-compose.yml, en la parte correspondiente a la base de datos tengo lo siguiente,

  mariadb:
    image: mariadb
    container_name: lc_mariadb
    restart: always
    init: true
    environment:
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db:/var/lib/mysql
    networks:
      - internal

Y la parte correspondiente a la copia de seguridad será algo como esto,

  backup:
    image: atareao/mariadb-backup:latest
    container_name: backup
    init: true
    restart: unless-stopped
    networks:
      - internal
    volumes:
      - ./hooks:/hooks
      - ./backup:/backup
    environment:
      MARIADB_DB: ${DB_NAME}
      MARIADB_HOST: mariadb
      MARIADB_PORT: 3306
      MARIADB_USER: ${DB_USER}
      MARIADB_PASSWORD: ${DB_PASSWORD}
      SCHEDULE: "* * 1/24 * * * *"
      BACKUP_KEEP_MINS: ${BACKUP_KEEP_MINS}
      BACKUP_KEEP_DAYS: ${BACKUP_KEEP_DAYS}
      BACKUP_KEEP_WEEKS: ${BACKUP_KEEP_WEEKS}
      BACKUP_KEEP_MONTHS: ${BACKUP_KEEP_MONTHS}

Todas las variables, las tengo en un archivo .env como el que te indico a continuación,

DB_USER=xxxxxxxxxxxxxxx
DB_PASSWORD=xxxxxxxxxxxxxxx
DB_NAME=xxxxxxxxxxxxxxx
DB_ROOT_PASSWORD=xxxxxxxxxxxxxxx
FQDN=tusitio.com
BACKUP_KEEP_MINS=1440
BACKUP_KEEP_DAYS=7
BACKUP_KEEP_WEEKS=4
BACKUP_KEEP_MONTHS=6

La ventaja de tenerlo así, es que me permite utilizarlo también en un script para forzar copias de seguridad. Un script como el que te muestro a continuación,

#!/bin/bash

set -o allexport
source .env
set +o allexport

NETWORK=internal

docker run  --rm \
            --init \
            -v "$PWD/backup:/backup" \
            -v "$PWD/hooks:/hooks" \
            --network $NETWORK \
            -e MARIADB_DB=${DB_NAME} \
            -e MARIADB_HOST=mariadb \
            -e MARIADB_USER=${DB_USER} \
            -e MARIADB_PASSWORD=${DB_PASSWORD} \
            -e BACKUP_KEEP_MINS=${BACKUP_KEEP_MINS} \
            -e BACKUP_KEEP_DAYS=${BACKUP_KEEP_DAYS} \
            -e BACKUP_KEEP_WEEKS=${BACKUP_KEEP_WEEKS} \
            -e BACKUP_KEEP_MONTHS=${BACKUP_KEEP_MONTHS} \
            atareao/mariadb-backup /app/backup.sh

Y para completar el trabajo, dentro del directorio hooks, tengo el siguiente script, 00-webhook que es el que se encarga de enviar la información a ZincObserve,

#!/bin/sh

set -e

# Possible actions: error, pre-backup, post-backup
ACTION="${1}"

WEBHOOK_URL="https://zincobserve.tusitio.es/api/default/backup/_json"
TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
WEB="tusitio.com"

case "${ACTION}" in
    "error")
        echo "Execute error webhook call to ${WEBHOOK_URL}"
        DATE=$(date "+%Y-%m-%d %H:%M:%S")
        curl --request POST \
             --url "${WEBHOOK_URL}" \
             --header "accept: application/json" \
             --header "Authorization: Basic ${TOKEN}" \
             --header "Content-Type: application/json" \
             --max-time 10 \
             --retry 5 \
             --data "[
                         {
                             \"result\": \"fail\",
                             \"web\": \"${WEB}\",
                             \"date\": \"${DATE}\"
                         }
                     ]"
        ;;
   "pre-backup")
       echo "Nothing to do"
       ;;
    "post-backup")
        echo "Execute post-backup webhook call to ${WEBHOOK_URL}"
        DATE=$(date "+%Y-%m-%d %H:%M:%S")
        curl --request POST \
             --url "${WEBHOOK_URL}" \
             --header "accept: application/json" \
             --header "Authorization: Basic ${TOKEN}" \
             --header "Content-Type: application/json" \
             --max-time 10 \
             --retry 5 \
             --data "[
                         {
                             \"result\": \"ok\",
                             \"web\": \"${WEB}\",
                             \"date\": \"${DATE}\"
                         }
                     ]"
      ;;
  esac

Espero que te haya gustado este nuevo episodio del podcast. Si puedes, te agradecería una valoración en iVoox y/o en Apple Podcast.

Más información,

1 comentario en “Cuatro Docker para emails, backup y mas

  1. LY
    Lynze hace 8 meses

    Hola.
    El enlace de Postgresql-Backup no funciona. Lleva a un 404 de Github.
    Gracias!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *