Docker: Ejecute Cronjob para un Contenedor diferente

Estoy buscando las mejores prácticas para ejecutar cronjobs para mi contenedor php fpm.

Ahora mismo corriendo:

  • Contenedor NGINX
  • Contenedor PHP FPM
  • Contenedor MySQL

Ahora me encantaría tener otro Contenedor en ejecución llamado "Contenedor Cronjob" que ejecute un script dentro de mi Contenedor PHP FPM ( necesito algunas dependencias de PHP ).

Así que tres posibles soluciones:

1.) Ejecutar un contenedor propio

Me encantaría usar esta solución!

Sería bueno tener un contenedor que ejecute CRON donde pueda (de alguna manera ) llamar a docker exec en mi contenedor php fpm... O de otra manera.

2.) Ejecutando CRON dentro del contenedor PHP

Esto estaría bien, pero no es la mejor práctica. Podría iniciar un segundo proceso dentro de mi contenedor php fpm ejecutando cron. Esto funcionaría, pero no estoy seguro de si este es el que debe trabajar con docker.

3.) Ejecutando Cron de Hosts

Esto sería cruel. Necesitaría encontrar el processID y el containerId de una ruta determinada y luego ejecutar docker exec. Pero este es más o menos mi último camino... Y odio administrar cronjobs sin implementación.

Entonces, ¿cuál es el mejor enfoque aquí?

Que tengas un buen día,

Bastian

He escrito un demonio que observa contenedores y programa trabajos, definidos en sus metadatos, en ellos. Esto se acerca más a su 1) solución. Ejemplo:

version: '2'services:  wordpress:    image: wordpress  mysql:    image: mariadb    volumes:      - ./database_dumps:/dumps    labels:      deck-chores.dump.command: sh -c "mysqldump --all-databases > /dumps/dump-$$(date -Idate)"      deck-chores.dump.interval: daily

También es posible una configuración "clásica", similar a cron.

Aquí están los docs, aquí está el repositorio de imágenes.

Cron se puede instalar y ejecutar en primer plano (cron -f) por lo que es muy fácil de instalar en un contenedor. Para acceder a otros contenedores, es probable que instale docker en el mismo contenedor para la CLI del cliente (no para ejecutar el demonio). Luego, para acceder al entorno docker del host, la solución más común es vincular mount the docker socket (-v /var/run/docker.sock:/var/run/docker.sock). El único problema es que debe configurar el gid de docker dentro de su contenedor para que coincida con el gid del host y luego agregar usuarios dentro del contenedor al grupo de docker.

Esto significa que esos usuarios tienen el mismo acceso que cualquier usuario de docker en el host, por ejemplo, acceso de nivel raíz, por lo que debe confiar completamente en el usuario que los envía o limitar los comandos que pueden ejecutar con algún tipo de equivalente de sudo. La otra desventaja es que es menos portátil y es poco probable que los administradores conscientes de la seguridad aprueben la ejecución de sus contenedores en sus sistemas.

La alternativa a la opción B es muy fácil con una herramienta como supervisord. Si bien es menos que el ideal de "un proceso por contenedor", tampoco es un antipatrón, ya que mantiene unidos todo el contenedor y las dependencias, y elimina cualquier riesgo de seguridad para el host.

Si opta por la primera o la segunda opción, todo se reduce a su entorno, quién envía los trabajos, cuántos contenedores necesitan que se envíen los trabajos contra sí mismos, etc. Si se trata de un administrador que envía trabajos en muchos contenedores, entonces un contenedor cron tiene sentido. Pero si eres el desarrollador de aplicaciones que necesita incluir un trabajo programado con tu aplicación como paquete, elige la segunda opción.

Ejecute cron en otro contenedor o incluso en el host, pero ejecute el script a través de php-fpm (p. ej. el cron "curl" o algo así el script PHP).

Asegúrese de proteger dicha configuración con un token de seguridad,limitaciones de red, etc. Una mejora podría ser tener un grupo php-fpm separado con procesos dinámicos que pueda generar un máximo de un proceso. Este grupo solo sería accesible por el cron. También podría beneficiarse de sus propias configuraciones individuales, como un mayor tiempo de ejecución, más o menos memoria, etc.

PD: Puedes usar algo como este para llamar al script directamente en el contenedor FPM y no pasar por nginx.

Razonamiento: Probablemente desee acceder a las mismas bibliotecas, la misma configuración, etc. Ejecutar un proceso generado aleatoriamente y no controlado por un administrador de señales en Docker es una muy mala idea.

Estaba tratando de lograr algo similar.

Mi idea inicial era comenzar trabajos cron por separado cron contenedor y ejecutarlos realmente dentro de otro contenedor (php)IE. para tener uno crontab registro para cada uno docker run -i t $containerName $scriptName ... comando que ejecuta un script diferente dentro del php contenedor

El enfoque no es realmente bueno debido a las desventajas @BMitch también menciona. Además, realmente no me gusta instalar docker al contenedor.

Me gustaría ofrecer otra solución que se ajuste a su #1 categoría: se puede correr el php-fpm directamente. Aunque no es la solución más elegante del mundo ofrece ventajas:

  1. Seguridad: sin acceso especial o privilegiado, solo use host y puerto (como php-host:9000) que ya está abierto para nginx desde la red virtual de Docker
  2. Tener cron gestión separada de la php contenedor, por lo que no se daña la escala
  3. Realmente usando cron para tareas de cronish, simplemente plante el crontab y hacerlo en lugar de reimplementar el cron a través de varias otras bibliotecas
  4. La ejecución del script no se ejecuta nginx, por lo que nadie puede ejecutarlos directamente a través del servidor web, no es necesario implementar ningún mecanismo de autenticación o similar
  5. Incluso menos problemas con los permisos. Mi dockerización cron anterior estaba teniendo cron instalado dentro de otro php contenedor y que la base de código se comparta mediante volúmenes. Eso era eficiente, pero los permisos tenían que manejarse con cuidado como cachés, DI, registros, etc. tenía que ser accesible y escribible tanto por el servidor web como por un cron usuario. Este enfoque elimina el problema

La única desventaja que encontré hasta ahora es que la primera línea con hashbang (#!/usr/local/bin/php) se considera una salida real y se emite una advertencia de PHP sobre los encabezados ya enviados (Cannot modify header information - headers already sent by ...)- soltar el hashbang soluciona esto.

¿Cómo hacerlo realmente?

  1. Tenga un recipiente limpio, por ejemplo alpine:3.7
  2. Instalar apk-cron y fcgi (información del paquete)
  3. Ejecuta algo como:
SCRIPT_FILENAME=/docroot/scripts/cron/example-script.php \REQUEST_METHOD=GET \cgi-fcgi -bind -connect php-fpm:9000

desde el crontab.

Más información sobre el tema: Conéctese directamente a PHP-FPM

Lo hice (con Docker Compose más o menos automáticamente), pero ¿cómo iniciarías algún tipo de trabajo cronológico basado en PHP solo con algún tipo de comando de red? Si uso el puerto 80, tengo el tiempo de espera normal de PHP en mi contra, lo que no tiene sentido… No estoy seguro de lo que sería una buena solución!

No es que entienda o pueda probar nada de esto, pero hay un ejemplo en ese documento que dice que puede ejecutar un comando como este docker run --rm name name web2 --link db:db2/webapp commandname, así que si eso funciona para usted, ejecute cron en un contenedor y haga que emita comandos como ese en los otros contenedores.

#1! - Lo siento, en realidad no lo sé. ¿No es el punto de los contenedores para que estén “contenidos”? Como, “seguro”? No uso contenedores docker o de aplicaciones, así que no se exactamente de lo que estoy hablando…

Tienes toda la razón, deberían estar “contenidos”, pero necesitas que algunos de ellos trabajen juntos como una sola pieza de software. Si no puede ejecutar su software como un solo proceso ( y para ser honesto, tan pronto como no sea un profesional en escribir su propia base de datos desde cero, no podrá hacerlo), necesita algunos contenedores para trabajar juntos. Y no se como ejecutar Cronjobs con ellos=/.

Comunicación entre contenedores (vinculación o creación de redes): Redirecting…