¿Cómo ejecutar un trabajo cron dentro de un contenedor acoplable?

275

Estoy tratando de ejecutar un cronjob dentro de un contenedor docker que invoca un script de shell.

Ayer estuve buscando en toda la web y el desbordamiento de pila, pero realmente no pude encontrar una solución que funcione.
¿Cómo puedo hacer esto?

EDITAR:

He creado un repositorio github (comentado) con un contenedor cron de Docker que funciona que invoca un script de shell en un intervalo determinado.

C Heyer
fuente

Respuestas:

365

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 -fno 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 tailposible 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 -fal final de una ventana acoplableCMD ".

VonC
fuente
1
Primero tuve que instalar cron, ya que no está incluido. Pero al agregar esto al Dockerfile funciona. ¡Gracias! RUN apt-get update && apt-get install cron
C Heyer
2
probablemente debería agregar -ya la instalación de cron para evitar que la construcción de
Docker
1
@Gaafar Derecha! Incluí tu comentario en la respuesta para mayor visibilidad y agregué otra opción.
VonC
66
¿Esta solución aún funciona? Cuando sigo las pautas dadas, cuando inicio sesión en el contenedor como root y tipo crontab -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 archivo Hello World). Estoy tirando esta imagen en mi Dockerfile: FROM phusion/baseimage:0.10.0. ¿Alguna idea sobre la discrepancia en el comportamiento?
Homunculus Reticulli
11
A partir de 2018, este enfoque ya no funciona; ¿Alguien ha podido hacer que su cronjob funcione con Ubuntu como imagen base? No estoy interesado en la imagen alpina que viene con cron corriendo de la caja
pelican
148

La solución adoptada puede ser peligrosa en un entorno de producción .

En Docker, solo debe ejecutar un proceso por contenedor porque si no lo hace, el proceso que se bifurcó y pasó a segundo plano no se supervisa y puede detenerse sin que usted lo sepa.

Cuando utiliza CMD cron && tail -f /var/log/cron.logel proceso cron básicamente fork para ejecutar cronen segundo plano, el proceso principal se cierra y le permite ejecutar tailfen 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á.

Puede evitar tal cosa al redirigir directamente la salida de comandos del cron a su acoplador stdouty stderrque se encuentran respectivamente en /proc/1/fd/1y /proc/1/fd/2.

Usando redireccionamientos básicos de shell, puede hacer algo como esto:

* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2

Y su CMD será: CMD ["cron", "-f"]

hugoShaka
fuente
14
Niza: cron -fes para "primer plano cron". He incluido su respuesta en la mía anterior, para mayor visibilidad. +1
VonC
Digamos que mi programa no genera nada. ¿Puedo seguir usando este método y asegurarme de que mi proceso no se detendrá en segundo plano?
Arcsector
1
@Arcsector este método evita poner un proceso en segundo plano, por eso no falla en silencio. Tener un proceso en segundo plano en un contenedor acoplable no es simple. Si desea tener un proceso en segundo plano en ejecución, es posible que desee utilizar un proceso de inicio para monitorear los múltiples procesos que ejecuta en el contenedor. Otra forma es iniciar el proceso en otro contenedor al lado del principal llamado 'sidecar'. A menudo, la mejor manera es evitar múltiples procesos en el contenedor.
hugoShaka
Bonito y limpio ! Me encanta :)
AmaelH
1
Esta es una buena solución y funciona bien para nosotros, aparte de un problema. Cuando el contenedor recibe una señal SIGTERM, no parece esperar a que finalice el proceso programado y se apaga con gracia, sino que está matando el proceso, lo que puede causar problemas.
James Hulse
107

Para aquellos que desean usar una imagen simple y liviana:

FROM alpine:3.6

# copy crontabs for root user
COPY config/cronjobs /etc/crontabs/root

# start crond with log level 8 in foreground, output to stderr
CMD ["crond", "-f", "-d", "8"]

Donde cronjobs es el archivo que contiene sus cronjobs, de esta forma:

* * * * * echo "hello stackoverflow" >> /test_file 2>&1
# remember to end this file with an empty new line
Oscar Fanelli
fuente
10
Imagen simple, ligera y estándar basada. Esta debería ser la respuesta aceptada. Utilice también la > /proc/1/fd/1 2> /proc/1/fd/2redirección para acceder a la salida de cronjobs directamente desde los registros de la ventana acoplable.
HenriTel
2
Para personas que no usan alpine: el crond que admite el -d 8parámetro no es el cron estándar, es el comando crond de busybox. Por ejemplo, desde ubuntu, puede ejecutar esto como busybox crond -f -d 8. Para versiones anteriores tienes que usar -L /dev/stdout/.
Trendfischer
2
Daría este +100 si pudiera. Esta es, con mucho, la mejor manera de ejecutar trabajos cron en un entorno Docker.
Jitsusama
1
Si no desea crear una nueva imagen cada vez que cambia el trabajo cron (o si necesita múltiples), puede ejecutar Alpine y usar un volumen para configurar el cron. He comprobado a cabo utilizando el siguiente: docker run -v ${PWD}/cronjobs:/etc/crontabs/root alpine:3.6 crond -f -d 8. @Groostav puede usar algo similar en Docker Compose.
dualidad_
1
CMD ["crond"o CMD ["cron"?
codemith
38

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.

FROM ubuntu:latest

# Install cron
RUN apt-get -y install cron

# Create the log file to be able to run tail
RUN touch /var/log/cron.log

# Setup cron job
RUN (crontab -l ; echo "* * * * * echo "Hello world" >> /var/log/cron.log") | crontab

# Run the command on container startup
CMD cron && tail -f /var/log/cron.log

Después de ejecutar su contenedor docker, puede asegurarse de que el servicio cron esté funcionando:

# To check if the job is scheduled
docker exec -ti <your-container-id> bash -c "crontab -l"
# To check if the cron service is running
docker exec -ti <your-container-id> bash -c "pgrep cron"

Si prefiere tener ENTRYPOINT en lugar de CMD, puede sustituir el CMD anterior con

ENTRYPOINT cron start && tail -f /var/log/cron.log
Youness
fuente
1
Alternativa interesante +1
VonC
2
RUN apt-get update && apt-get -y install crono de lo contrario no podrá encontrar el paquetecron
alphabetasoup
2
Gracias Youness, que me dio la idea de hacer lo siguiente, que trabajó en mi caso en el que se especifica cada uno de cron en un archivo diferente: RUN cat $APP_HOME/crons/* | crontab como un encanto :)
marcostvz
agregar crona un script de punto de entrada parece ser la mejor opción: ENTRYPOINT ["entrypoint.sh"]
bozdoz
20

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.ymlarchivo, que ejecutará algunas tareas para usted

version: "2"

services:
    tasker:
        image: strm/tasker
        volumes:
            - "/var/run/docker.sock:/var/run/docker.sock"
        environment:
            configuration: |
                logging:
                    level:
                        ROOT: WARN
                        org.springframework.web: WARN
                        sh.strm: DEBUG
                schedule:
                    - every: minute
                      task: hello
                    - every: minute
                      task: helloFromPython
                    - every: minute
                      task: helloFromNode
                tasks:
                    docker:
                        - name: hello
                          image: debian:jessie
                          script:
                              - echo Hello world from Tasker
                        - name: helloFromPython
                          image: python:3-slim
                          script:
                              - python -c 'print("Hello world from python")'
                        - name: helloFromNode
                          image: node:8
                          script:
                              - node -e 'console.log("Hello from node")'

Hay 3 tareas allí, todas se ejecutarán cada minuto ( every: minute), y cada una de ellas ejecutará el scriptcódigo, dentro de la imagen definida en la imagesección.

Solo corre docker-compose upy mira cómo funciona. Aquí está el repositorio de Tasker con la documentación completa:

http://github.com/opsxcq/tasker

OPSXCQ
fuente
La Dockerception (ejecutar contenedores Docker desde otro contenedor) es una mala práctica y debe limitarse a la integración continua. Una solución alternativa sería usar docker execen contenedores especificados.
HenriTel
1
Tasker no usa docker en docker (Dind / Dockerception), tenga en cuenta que se pasa el zócalo de docker como una asignación, todos los contenedores generados se generan en el demonio que ejecuta tasker. Y si no desea ejecutar Tasker dentro de Docker, puede implementarlo como cualquier otra aplicación.
OPSXCQ
1
No obtengo las ventajas de usar tasker. Me parece una exageración usar java y sh *** solo para ejecutar un trabajo cron.
Karl Adler
La combinación de cron y la imagen base que necesita (python / node, por ejemplo) crea una dependencia adicional que debe mantenerse e implementarse, en este escenario todos los trabajos comparten el mismo contenedor, lo que significa que debe preocuparse por limpiar todo después cada trabajo corre. Los trabajos que se ejecutan en Tasker son idempotentes, por lo que tiene menos cosas de qué preocuparse.
OPSXCQ
13

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.logcomando 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.

vanugrah
fuente
9

Aunque esto tiene como objetivo ejecutar trabajos junto a un proceso en ejecución en un contenedor a través de la execinterfaz 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:

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

'Clásico', la configuración de tipo cron también es posible.

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

futuro funky
fuente
Gracias. Esta respuesta es la más adecuada para el entorno de contenedores Docker. No hay cambios en las imágenes de Docker, solo agrega un contenedor especial para ejecutar tareas, funciona como un comando docker exec <container_name> <some_command>por programación.
PRIHLOP
Esta es la respuesta más simple y clara de "hacer el trabajo".
Ibrahim Awad
9

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:

FROM gaafar/cron

# COPY crontab file in the cron directory
COPY crontab /etc/cron.d/crontab

# Add your commands here

Como referencia, la imagen está aquí .

gafi
fuente
Imagen interesante +1
VonC
5

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.

[program:misc]
command=/etc/init.d/cron restart
user=root
autostart=true
autorestart=true
stderr_logfile=/var/log/misc-cron.err.log
stdout_logfile=/var/log/misc-cron.out.log
priority=998
Sagar Ghuge
fuente
Recibo un error en supervisor.log que indica que el servicio cron se detuvo varias veces y entró en estado FATAL. Sin embargo, cron parece estar ejecutándose en la parte superior y ejecutando cronjobs normalmente. ¡Gracias por esto!
lephleg
Sí, a mí también me pasó lo mismo, pero funciona de manera normal, así que no necesito molestarme.
Sagar Ghuge
5

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.

#docker-compose.yml
version: "3.3"
services:
    myservice:
      environment:
        MSG: i'm being cronjobbed, every minute!
      image: alpine
      container_name: myservice
      command: tail -f /dev/null

    cronjobber:
     image: docker:edge
     volumes:
      - /var/run/docker.sock:/var/run/docker.sock
     container_name: cronjobber
     command: >
          sh -c "
          echo '* * * * * docker exec myservice printenv | grep MSG' > /etc/crontabs/root
          && crond -f"
Jakob Eriksson
fuente
No pude hacer que esto funcionara con el enjambre Docker. Obteniendo myservice unknownerrores.
Mark Grimes
Debería haber una advertencia sobre el impacto de alta seguridad que tiene montar un zócalo acoplable: lvh.io/posts/…
casual
4

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:

FROM ubuntu:latest

RUN apt-get update && apt-get -y install cron
RUN apt-get update && apt-get install -y dos2unix

# Add crontab file (from your windows host) to the cron directory
ADD cron/hello-cron /etc/cron.d/hello-cron

# Change line ending format to LF
RUN dos2unix /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/hello-cron.log

# Run the command on container startup
CMD cron && tail -f /var/log/hello-cron.log

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!

Andreas Forslöw
fuente
3

De los ejemplos anteriores, creé esta combinación:

Alpine Image & Edit usando Crontab en Nano (Odio vi)

FROM alpine

RUN apk update
RUN apk add curl nano

ENV EDITOR=/usr/bin/nano 

# start crond with log level 8 in foreground, output to stderr
CMD ["crond", "-f", "-d", "8"]

# Shell Access
# docker exec -it <CONTAINERID> /bin/sh

# Example Cron Entry
# crontab -e
# * * * * * echo hello > /proc/1/fd/1 2>/proc/1/fd/2
# DATE/TIME WILL BE IN UTC
Dan Watts
fuente
2

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.

#!/bin/bash
timestamp=`date +%Y/%m/%d-%H:%M:%S`
echo "System path is $PATH at $timestamp"

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

#!/bin/bash

# Start the run once job.
echo "Docker container has been started"

# Setup a cron schedule
echo "* * * * * /run.sh >> /var/log/cron.log 2>&1
# This extra line makes it a valid cron" > scheduler.txt

crontab scheduler.txt
cron -f

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:

  1. Agregue la siguiente línea en entrypoint.sh
declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env
  1. Actualice la configuración de cron y especifique
SHELL=/bin/bash
BASH_ENV=/container.env

Por fin, entrypoint.shdebería verse como

#!/bin/bash

# Start the run once job.
echo "Docker container has been started"

declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env

# Setup a cron schedule
echo "SHELL=/bin/bash
BASH_ENV=/container.env
* * * * * /run.sh >> /var/log/cron.log 2>&1
# This extra line makes it a valid cron" > scheduler.txt

crontab scheduler.txt
cron -f

Por último, pero no menos importante: crea un Dockerfile

FROM ubuntu:16.04
MAINTAINER Himanshu Gupta

# Install cron
RUN apt-get update && apt-get install -y cron

# Add files
ADD run.sh /run.sh
ADD entrypoint.sh /entrypoint.sh

RUN chmod +x /run.sh /entrypoint.sh

ENTRYPOINT /entrypoint.sh

Eso es. ¡Construye y ejecuta la imagen de Docker!

himanshuIIITian
fuente
1
@himanshuIIITian Intenté esto, el problema es que el guión del "ejecutar una vez trabajo" nunca regresa y también el maíz -f no regresa, así que ... esto no funciona para mí, ¿alguna idea? gracias
Doron Levi
@DoronLevi: ¿podría compartir algunos registros para analizar el problema? O puede consultar el código completo desde aquí - github.com/nehabhardwaj01/docker-cron
himanshuIIITian
Gracias por la respuesta. Me alegra que la respuesta haya sido útil.
himanshuIIITian
1

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í:

crontab -l > cronexample
echo "00 09 * * 1-5 echo hello" >> cronexample
crontab cronexample
rm cronexample

Esto creará un archivo temporal con la tarea cron, luego lo programará usando crontab. Última línea eliminar archivo temporal.

Jesus Segnini
fuente
El crondemonio normalmente no se ejecuta en un contenedor.
Matt
@BhargavNanekalva debe configurarse específicamente en un contenedor que esta respuesta no aborda.
Matt
@ Matt, ¿podría indicar cómo se debe especificar exactamente en el contenedor? . Hago crontab -l y se muestra el comando - kagda.ru/i/6d014816d43_29-06-2017-11:38:59_6d01.png pero aún no se ejecuta
Tebe
@ Копать_Шо_я_нашел Debe ejecutar crondademá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 adecuada
Matt
1

Al ejecutar algunas imágenes recortadas que restringen el acceso de root, tuve que agregar mi usuario a los sudoers y ejecutar como sudo cron

FROM node:8.6.0
RUN apt-get update && apt-get install -y cron sudo

COPY crontab /etc/cron.d/my-cron
RUN chmod 0644 /etc/cron.d/my-cron
RUN touch /var/log/cron.log

# Allow node user to start cron daemon with sudo
RUN echo 'node ALL=NOPASSWD: /usr/sbin/cron' >>/etc/sudoers

ENTRYPOINT sudo cron && tail -f /var/log/cron.log

Tal vez eso ayude a alguien

Senica Gonzalez
fuente
Creo que la imagen del nodo utiliza el usuario del nodo; entonces quizás necesites agregar permisos para ese usuario
bozdoz
1

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.

Di Santi
fuente
-1

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

Krasi Georgiev
fuente
Las respuestas deben ser independientes y no estar
vinculadas a
-2

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.

every(1.day, 'Import large data from csv files', :at => '5:00') do |job|
  `rake 'portal:import_data_from_csv'`
end

Cree un contenedor separado en el archivo docker-compose y ejecute el siguiente comando dentro del contenedor.

command: bundle exec clockwork lib/clock.rb
Shobha Deepak
fuente
1
Buena idea usar alguna otra herramienta para programar. Sin embargo, esta pregunta pedía específicamente cron, por lo que su sugerencia sería mejor como un comentario a la pregunta en mi opinión.
Richard Kiefer