Puede copiar su crontab en una imagen, para que el contenedor lanzado desde dicha imagen ejecute el trabajo.
Consulte " Ejecutar un trabajo cron con Docker " de Julien Boulay en su Ekito/docker-cron
:
Creemos un nuevo archivo llamado " hello-cron
" para describir nuestro trabajo.
* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.
El siguiente Dockerfile describe todos los pasos para construir su imagen.
FROM ubuntu:latest
MAINTAINER docker@ekito.fr
RUN apt-get update && apt-get -y install cron
# Copy hello-cron file to the cron.d directory
COPY hello-cron /etc/cron.d/hello-cron
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
# Apply cron job
RUN crontab /etc/cron.d/hello-cron
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log
(vea el comentario de Gaafar y ¿Cómo hago que la instalación sea menos ruidosa ? : puede funcionar también)apt-get
apt-get -y install -qq --force-yes cron
Como señaló Nathan Lloyd en los comentarios :
Nota rápida sobre un problema:
si agrega un archivo de script y le dice a cron que lo ejecute, recuerde que Cron falla en silencio si lo olvida .
RUN chmod 0744 /the_script
O, asegúrese de que su trabajo en sí mismo redirija directamente a stdout / stderr en lugar de un archivo de registro, como se describe en la respuesta de hugoShaka :
* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2
Reemplace la última línea de Dockerfile con
CMD ["cron", "-f"]
Ver también (acerca de cron -f
, es decir cron "primer plano") " docker ubuntu cron -f
no funciona "
Construir y ejecutarlo:
sudo docker build --rm -t ekito/cron-example .
sudo docker run -t -i ekito/cron-example
Sea paciente, espere 2 minutos y su línea de comando debería mostrar:
Hello world
Hello world
Eric agrega en los comentarios :
Tenga en cuenta que es tail
posible que no muestre el archivo correcto si se crea durante la creación de la imagen.
Si ese es el caso, debe crear o tocar el archivo durante el tiempo de ejecución del contenedor para que tail pueda recoger el archivo correcto.
Consulte " No se muestra la salida de tail -f
al final de una ventana acoplableCMD
".
RUN apt-get update && apt-get install cron
-y
a la instalación de cron para evitar que la construcción decrontab -l
, obtengo No crontab instalado para root , también, mi pantalla permanece en blanco. Sin embargo, cuando verifico '/etc/cron.d/', veo que el crontab fiel está allí (y aún más sorprendente), cuando verifico/var/log/cron.log
, veo que el script se está ejecutando (se está agregando el contenido del archivoHello World
). Estoy tirando esta imagen en mi Dockerfile:FROM phusion/baseimage:0.10.0
. ¿Alguna idea sobre la discrepancia en el comportamiento?La solución adoptada puede ser peligrosa en un entorno de producción .
Cuando utiliza
CMD cron && tail -f /var/log/cron.log
el proceso cron básicamente fork para ejecutarcron
en segundo plano, el proceso principal se cierra y le permite ejecutartailf
en primer plano. El proceso cron en segundo plano podría detenerse o fallar, no lo notará, su contenedor seguirá ejecutándose en silencio y su herramienta de orquestación no lo reiniciará.Usando redireccionamientos básicos de shell, puede hacer algo como esto:
Y su CMD será:
CMD ["cron", "-f"]
fuente
cron -f
es para "primer plano cron". He incluido su respuesta en la mía anterior, para mayor visibilidad. +1Para aquellos que desean usar una imagen simple y liviana:
Donde cronjobs es el archivo que contiene sus cronjobs, de esta forma:
fuente
> /proc/1/fd/1 2> /proc/1/fd/2
redirección para acceder a la salida de cronjobs directamente desde los registros de la ventana acoplable.-d 8
parámetro no es el cron estándar, es el comando crond de busybox. Por ejemplo, desde ubuntu, puede ejecutar esto comobusybox crond -f -d 8
. Para versiones anteriores tienes que usar-L /dev/stdout/
.docker run -v ${PWD}/cronjobs:/etc/crontabs/root alpine:3.6 crond -f -d 8
. @Groostav puede usar algo similar en Docker Compose.CMD ["crond"
oCMD ["cron"
?Lo que ha sugerido @VonC es bueno, pero prefiero hacer toda la configuración del trabajo cron en una sola línea. Esto evitaría problemas de plataforma cruzada como la ubicación de cronjob y no necesita un archivo cron separado.
Después de ejecutar su contenedor docker, puede asegurarse de que el servicio cron esté funcionando:
Si prefiere tener ENTRYPOINT en lugar de CMD, puede sustituir el CMD anterior con
fuente
RUN apt-get update && apt-get -y install cron
o de lo contrario no podrá encontrar el paquetecron
RUN cat $APP_HOME/crons/* | crontab
como un encanto :)cron
a un script de punto de entrada parece ser la mejor opción: ENTRYPOINT ["entrypoint.sh"]Hay otra forma de hacerlo, es usar Tasker , un corredor de tareas que tiene soporte cron (un planificador).
Por qué ? A veces, para ejecutar un trabajo cron, debe mezclar su imagen base (python, java, nodejs, ruby) con el crond. Eso significa otra imagen para mantener. Tasker evita eso desacoplando el crond y tu contenedor. Puede centrarse en la imagen que desea ejecutar sus comandos y configurar Tasker para usarla.
Aquí un
docker-compose.yml
archivo, que ejecutará algunas tareas para ustedHay 3 tareas allí, todas se ejecutarán cada minuto (
every: minute
), y cada una de ellas ejecutará elscript
código, dentro de la imagen definida en laimage
sección.Solo corre
docker-compose up
y mira cómo funciona. Aquí está el repositorio de Tasker con la documentación completa:http://github.com/opsxcq/tasker
fuente
docker exec
en contenedores especificados.La respuesta de VonC es bastante exhaustiva. Además, me gustaría agregar una cosa que me ayudó. Si solo desea ejecutar un trabajo cron sin seguir un archivo, se verá tentado a eliminarlo del
&& tail -f /var/log/cron.log
comando cron.Sin embargo, esto hará que el contenedor Docker salga poco después de ejecutarse porque cuando se completa el comando cron, Docker piensa que el último comando ha salido y, por lo tanto, mata el contenedor. Esto se puede evitar ejecutando cron en primer plano a través de
cron -f
.fuente
Aunque esto tiene como objetivo ejecutar trabajos junto a un proceso en ejecución en un contenedor a través de la
exec
interfaz de Docker , esto puede ser de su interés.He escrito un demonio que observa contenedores y programa trabajos, definidos en sus metadatos, en ellos. Ejemplo:
'Clásico', la configuración de tipo cron también es posible.
Aquí están los documentos , aquí está el repositorio de imágenes .
fuente
docker exec <container_name> <some_command>
por programación.Creé una imagen de Docker basada en las otras respuestas, que se puede usar como
docker run -v "/path/to/cron:/etc/cron.d/crontab" gaafar/cron
donde
/path/to/cron
: ruta absoluta al archivo crontab, o puede usarlo como base en un Dockerfile:Como referencia, la imagen está aquí .
fuente
Cuando implemente su contenedor en otro host, solo tenga en cuenta que no iniciará ningún proceso automáticamente. Debe asegurarse de que el servicio 'cron' se esté ejecutando dentro de su contenedor. En nuestro caso, estoy usando Supervisord con otros servicios para iniciar el servicio cron.
fuente
Defina el cronjob en un contenedor dedicado que ejecute el comando a través de docker exec a su servicio.
Esto es una mayor cohesión y el script en ejecución tendrá acceso a las variables de entorno que haya definido para su servicio.
fuente
myservice unknown
errores.Si está utilizando Docker para Windows, recuerde que debe cambiar su formato de final de línea de CRLF a LF (es decir, de dos a unix) si tiene la intención de importar su archivo crontab de Windows a su contenedor ubuntu. Si no, su trabajo cron no funcionará. Aquí hay un ejemplo de trabajo:
En realidad, esto me llevó horas averiguarlo, ya que depurar trabajos cron en contenedores docker es una tarea tediosa. ¡Espero que ayude a alguien más que no puede hacer que su código funcione!
fuente
De los ejemplos anteriores, creé esta combinación:
Alpine Image & Edit usando Crontab en Nano (Odio vi)
fuente
Configurar un cron en paralelo a un trabajo de una sola vez
Cree un archivo de script, por ejemplo, run.sh, con el trabajo que se supone que debe ejecutarse periódicamente.
Guardar y Salir.
Use Entrypoint en lugar de CMD
Si tiene varios trabajos para iniciar durante la contenedorización de Docker, use el archivo de punto de entrada para ejecutarlos todos.
El archivo de punto de entrada es un archivo de script que entra en acción cuando se emite un comando de ejecución de Docker. Por lo tanto, todos los pasos que queremos ejecutar se pueden colocar en este archivo de script.
Por ejemplo, tenemos 2 trabajos para ejecutar:
Ejecutar una vez trabajo : echo "El contenedor Docker se ha iniciado"
Ejecute trabajo periódico : run.sh
Crear entrypoint.sh
Comprendamos el crontab que se ha configurado en el archivo
* * * * *
: Horario de Cron; El trabajo debe ejecutarse cada minuto. Puede actualizar la programación según sus requisitos./run.sh
: La ruta al archivo de script que se ejecutará periódicamente/var/log/cron.log
: El nombre de archivo para guardar la salida del trabajo cron programado.2>&1
: Los registros de errores (si los hay) también se redirigirán al mismo archivo de salida utilizado anteriormente.Nota : No olvide agregar una nueva línea adicional, ya que la convierte en un cron válido.
Scheduler.txt
: la configuración cron completa se redirigirá a un archivo.Uso de variables de entorno específicas del sistema / usuario en cron
Mi trabajo cron real esperaba la mayoría de los argumentos a medida que las variables de entorno pasaron al comando de ejecución de Docker. Pero, con bash, no pude usar ninguna de las variables de entorno que pertenecen al sistema o al contenedor acoplable.
Entonces, esto surgió como una solución a este problema:
Por fin,
entrypoint.sh
debería verse comoPor último, pero no menos importante: crea un Dockerfile
Eso es. ¡Construye y ejecuta la imagen de Docker!
fuente
Los trabajos de Cron se almacenan en / var / spool / cron / crontabs (lugar común en todas las distribuciones que conozco). Por cierto, puedes crear una pestaña cron en bash usando algo así:
Esto creará un archivo temporal con la tarea cron, luego lo programará usando crontab. Última línea eliminar archivo temporal.
fuente
cron
demonio normalmente no se ejecuta en un contenedor.crond
además del servicio que está ejecutando en el contenedor, normalmente con un administrador de servicios como s6. Probablemente haga eso como una pregunta para obtener una respuesta adecuadaAl ejecutar algunas imágenes recortadas que restringen el acceso de root, tuve que agregar mi usuario a los sudoers y ejecutar como
sudo cron
Tal vez eso ayude a alguien
fuente
Entonces, mi problema era el mismo. La solución fue cambiar la sección de comandos en el
docker-compose.yml
.De
comando: crontab / etc / crontab && tail -f / etc / crontab
A
comando: crontab / etc / crontab
comando: tail -f / etc / crontab
El problema era el '&&' entre los comandos. Después de eliminar esto, todo estuvo bien.
fuente
La forma más sólida que he encontrado hasta ahora es ejecutar un contenedor cron independiente: instale el cliente de Docker y monte el Docker Sock para que pueda hablar con el servidor de Docker en el host.
Luego, use env vars para cada trabajo cron y un script de punto de entrada para generar / etc / crontab
Aquí hay una imagen que creé usando este principio y usándola en producción durante los últimos 3-4 años.
https://www.vip-consult.solutions/post/better-docker-cron#content
fuente
Intente usar una gema mecánica para programar tareas. Siga los pasos provistos en este enlace.
http://fuzzyblog.io/blog/rails/2017/05/11/adding-cron-to-a-dockerized-rails-application-using-clockwork.html
Puede llamar a la tarea de rastrillo dentro del archivo lib / clock.rb como se muestra a continuación.
Cree un contenedor separado en el archivo docker-compose y ejecute el siguiente comando dentro del contenedor.
fuente