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
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,
Hola.
El enlace de Postgresql-Backup no funciona. Lleva a un 404 de Github.
Gracias!