Wie führe ich einen Cron-Job in einem Docker-Container aus?

275

Ich versuche, einen Cronjob in einem Docker-Container auszuführen, der ein Shell-Skript aufruft.

Gestern habe ich im gesamten Web gesucht und einen Stapelüberlauf durchgeführt, aber ich konnte keine wirklich funktionierende Lösung finden.
Wie kann ich das machen?

BEARBEITEN:

Ich habe ein (kommentiertes) Github-Repository mit einem funktionierenden Docker-Cron-Container erstellt, der in einem bestimmten Intervall ein Shell-Skript aufruft.

C Heyer
quelle

Antworten:

364

Sie können Ihre Crontab in ein Image kopieren, damit der von diesem Image gestartete Container den Job ausführt.

Siehe " Führen Sie einen Cron-Job mit Docker aus " von Julien Boulay in seinem Ekito/docker-cron:

Erstellen wir eine neue Datei mit dem Namen " hello-cron", um unseren Job zu beschreiben.

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

Die folgende Docker-Datei beschreibt alle Schritte zum Erstellen Ihres Images

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

(siehe Gaafar ‚s Kommentar und Wie kann ich apt-getweniger laut installieren? :
apt-get -y install -qq --force-yes cronkann auch funktionieren)

Wie von Nathan Lloyd in den Kommentaren bemerkt :

Kurzer Hinweis zu einem Gotcha:
Wenn Sie eine Skriptdatei hinzufügen und cron anweisen, sie auszuführen, denken Sie daran, dass Cron im Hintergrund fehlschlägt, wenn Sie es vergessen .
RUN chmod 0744 /the_script


ODER stellen Sie sicher, dass Ihr Job selbst direkt zu stdout / stderr anstatt zu einer Protokolldatei umleitet, wie in der Antwort von hugoShaka beschrieben :

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

Ersetzen Sie die letzte Dockerfile-Zeile durch

CMD ["cron", "-f"]

Siehe auch (ungefähr cron -f, das heißt cron "Vordergrund") " Docker Ubuntu cron -ffunktioniert nicht "


Erstellen und ausführen Sie es:

sudo docker build --rm -t ekito/cron-example .
sudo docker run -t -i ekito/cron-example

Seien Sie geduldig, warten Sie 2 Minuten und Ihre Befehlszeile sollte Folgendes anzeigen:

Hello world
Hello world

Eric fügt in den Kommentaren hinzu :

Beachten Sie, dass tailmöglicherweise nicht die richtige Datei angezeigt wird, wenn sie während der Image-Erstellung erstellt wird.
In diesem Fall müssen Sie die Datei zur Laufzeit des Containers erstellen oder berühren, damit der Tail die richtige Datei aufnimmt.

Siehe " Ausgabe tail -fam Ende eines Dockers CMDwird nicht angezeigt ".

VonC
quelle
1
Ich musste zuerst cron installieren, da es nicht enthalten ist. Aber wenn Sie dies zur Docker-Datei hinzufügen, funktioniert es. Vielen Dank! RUN apt-get update && apt-get install cron
C Heyer
2
Sie sollten wahrscheinlich -yzur Installation von cron hinzufügen, um zu vermeiden, dass der Docker-Build beendet wird
gafi
1
@ Gaafar Richtig! Ich habe Ihren Kommentar zur besseren Sichtbarkeit in die Antwort aufgenommen und eine weitere Option hinzugefügt.
VonC
6
Funktioniert diese Lösung noch? Wenn ich die angegebenen Richtlinien befolge und mich als root und type in den Container einlogge crontab -l, wird kein crontab für root installiert . Außerdem bleibt mein Bildschirm leer. Wenn ich jedoch '/etc/cron.d/' überprüfe, sehe ich, dass das crontab-Feld vorhanden ist (und noch überraschender), wenn ich überprüfe /var/log/cron.log, sehe ich, dass das Skript ausgeführt wird (der Dateiinhalt wird angehängt Hello World). Ich ziehe dieses Bild in meine Docker-Datei : FROM phusion/baseimage:0.10.0. Irgendwelche Ideen zur Diskrepanz im Verhalten?
Homunculus Reticulli
11
Ab 2018 funktioniert dieser Ansatz nicht mehr. Hat es jemand geschafft, seinen Cronjob dazu zu bringen, mit Ubuntu als Basis-Image zu arbeiten? Ich bin nicht an dem alpinen Bild interessiert, das mit Cron kommt, der aus der Box
herausläuft
145

Die angenommene Lösung kann in einer Produktionsumgebung gefährlich sein .

In Docker sollten Sie nur einen Prozess pro Container ausführen, da sonst der Prozess, der den Hintergrund gegabelt und verschoben hat, nicht überwacht wird und möglicherweise gestoppt wird, ohne dass Sie es wissen.

Wenn Sie CMD cron && tail -f /var/log/cron.logden Cron-Prozess grundsätzlich fork verwenden, um ihn cronim Hintergrund auszuführen , wird der Hauptprozess beendet und Sie können ihn tailfim Vordergrund ausführen . Der Hintergrund-Cron-Prozess kann angehalten werden oder fehlschlagen, Sie werden es nicht bemerken, Ihr Container wird weiterhin still ausgeführt und Ihr Orchestrierungs-Tool startet ihn nicht neu.

Sie können durch Umleitung direkt die Befehle Ausgabe des cron in Ihren Docker so etwas vermeiden stdoutund stderrdie jeweils angeordnet sind in /proc/1/fd/1und /proc/1/fd/2.

Mit einfachen Shell-Weiterleitungen möchten Sie möglicherweise Folgendes tun:

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

Und Ihre CMD wird sein: CMD ["cron", "-f"]

hugoShaka
quelle
14
Schön: cron -fist für "Cron Vordergrund". Ich habe Ihre Antwort oben in meine aufgenommen, um mehr Sichtbarkeit zu gewährleisten. +1
VonC
Angenommen, mein Programm gibt nichts aus. Kann ich diese Methode weiterhin verwenden und sicherstellen, dass mein Prozess nicht im Hintergrund stoppt?
Arcsector
1
@Arcsector Diese Methode vermeidet es, einen Prozess in den Hintergrund zu stellen. Deshalb schlägt er nicht stillschweigend fehl. Ein Hintergrundprozess in einem Docker-Container ist nicht einfach. Wenn Sie einen laufenden Hintergrundprozess haben möchten, können Sie einen Init-Prozess verwenden, um die mehreren Prozesse zu überwachen, die Sie im Container ausführen. Eine andere Möglichkeit besteht darin, den Prozess in einem anderen Container neben dem Hauptcontainer namens "Beiwagen" zu starten. Der beste Weg ist oft, mehrere Prozesse im Container zu vermeiden.
HugoShaka
Schön und sauber !
Ich
1
Dies ist eine gute Lösung und funktioniert abgesehen von einem Problem gut für uns. Wenn der Container ein SIGTERM-Signal empfängt, scheint er nicht auf den Abschluss des geplanten Prozesses und das ordnungsgemäße Herunterfahren zu warten, sondern beendet den Prozess, der Probleme verursachen kann.
James Hulse
106

Für diejenigen, die ein einfaches und leichtes Bild verwenden möchten:

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"]

Wobei cronjobs die Datei ist, die Ihre cronjobs enthält, in dieser Form:

* * * * * echo "hello stackoverflow" >> /test_file 2>&1
# remember to end this file with an empty new line
Oscar Fanelli
quelle
10
Einfach, leicht und standardbildbasiert. Dies sollte die akzeptierte Antwort sein. Verwenden Sie die > /proc/1/fd/1 2> /proc/1/fd/2Umleitung auch, um auf Cronjobs zuzugreifen, die direkt aus den Docker-Protokollen ausgegeben werden.
HenriTel
2
Für Personen, die nicht alpine verwenden: Der crond, der den -d 8Parameter unterstützt, ist nicht der Standard-cron, sondern der crond-Befehl von busybox. Zum Beispiel können Sie dies von Ubuntu aus als ausführen busybox crond -f -d 8. Für ältere Versionen müssen Sie verwenden -L /dev/stdout/.
Trendfischer
Für meine Bedürfnisse - die Emulation einer Produktionseinstellung von unabhängig laufenden Cron-Jobs, bei denen ich sehen muss, was passiert - ist dies großartig.
Thorbjørn Ravn Andersen
2
Ich würde diese +100 geben, wenn ich könnte. Dies ist bei weitem der beste Weg, um Cron-Jobs in einer Docker-Umgebung auszuführen.
Jitsusama
1
Wenn Sie nicht jedes Mal ein neues Image erstellen möchten, wenn Sie den Cron-Job ändern (oder wenn Sie mehrere benötigen), können Sie einfach Alpine ausführen und ein Volume zum Einstellen des Cron verwenden. Ich habe es mit folgendem getestet : docker run -v ${PWD}/cronjobs:/etc/crontabs/root alpine:3.6 crond -f -d 8. @Groostav Sie können eine ähnliche Sache in Docker Compose verwenden.
Dualität_
38

Was @VonC vorgeschlagen hat, ist nett, aber ich bevorzuge es, alle Cron-Job-Konfigurationen in einer Zeile durchzuführen. Dies würde plattformübergreifende Probleme wie den Cronjob-Standort vermeiden und Sie benötigen keine separate Cron-Datei.

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

Nachdem Sie Ihren Docker-Container ausgeführt haben, können Sie sicherstellen, dass der Cron-Service funktioniert durch:

# 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"

Wenn Sie ENTRYPOINT anstelle von CMD bevorzugen, können Sie das obige CMD durch ersetzen

ENTRYPOINT cron start && tail -f /var/log/cron.log
Youness
quelle
1
Interessante Alternative. +1
VonC
2
RUN apt-get update && apt-get -y install cronoder es wird nicht in der Lage sein, Paket zu findencron
alphabetasoup
2
Danke Youness, du hast mir die Idee gegeben, Folgendes zu tun, was in meinem Fall funktioniert hat, in dem jeder Cron in einer anderen Datei angegeben ist: RUN cat $APP_HOME/crons/* | crontab Wie ein Zauber :)
marcostvz
Das Hinzufügen cronzu einem Einstiegspunktskript scheint die beste Option zu sein: ENTRYPOINT ["entrypoint.sh"]
bozdoz
20

Eine andere Möglichkeit besteht darin, Tasker zu verwenden , einen Task-Runner, der Cron (einen Scheduler) unterstützt.

Warum ? Manchmal müssen Sie zum Ausführen eines Cron-Jobs Ihr Basis-Image (Python, Java, NodeJS, Ruby) mit dem Cron mischen. Das bedeutet, dass ein anderes Image beibehalten werden muss. Tasker vermeiden Sie dies, indem Sie den Crond und Ihren Container entkoppeln. Sie können sich einfach auf das Bild konzentrieren, auf dem Sie Ihre Befehle ausführen möchten, und Tasker für die Verwendung konfigurieren.

Hier eine docker-compose.ymlDatei, die einige Aufgaben für Sie ausführt

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")'

Dort gibt es 3 Aufgaben, die alle jede Minute ausgeführt werden ( every: minute), und jede von ihnen führt den scriptCode innerhalb des im imageAbschnitt definierten Bildes aus .

Laufen Sie einfach docker-compose upund sehen Sie, wie es funktioniert. Hier ist das Tasker-Repo mit der vollständigen Dokumentation:

http://github.com/opsxcq/tasker

OPSXCQ
quelle
Dockerception (Ausführen von Docker-Containern von einem anderen Container aus) ist eine schlechte Praxis und sollte auf die kontinuierliche Integration beschränkt werden. Eine Problemumgehung wäre die Verwendung docker execfür bestimmte Container.
HenriTel
1
Tasker verwendet Docker nicht in Docker (Dind / Dockerception). Beachten Sie, dass der Docker-Socket als Zuordnung übergeben wird. Alle erzeugten Container befinden sich in dem Daemon, den Tasker ausführt. Wenn Sie den Tasker nicht im Docker ausführen möchten, können Sie ihn einfach wie jede andere Anwendung bereitstellen.
OPSXCQ
1
Ich habe nicht die Vorteile, Tasker zu verwenden. Scheint mir wirklich ein Overkill zu sein, wenn ich Java und Sh *** benutze, nur um einen Cron-Job auszuführen.
Karl Adler
Durch das Mischen von Cron und dem von Ihnen benötigten Basis-Image (z. B. Python / Node) wird eine zusätzliche Abhängigkeit erstellt, die beibehalten und bereitgestellt werden muss. In diesem Szenario teilen sich alle Jobs denselben Container. Dies bedeutet, dass Sie sich darum kümmern müssen, alles danach zu bereinigen Jeder Job läuft. Jobs, die auf Tasker ausgeführt werden, sind idempotent, sodass Sie sich weniger Sorgen machen müssen.
OPSXCQ
13

VonCs Antwort ist ziemlich gründlich. Außerdem möchte ich eine Sache hinzufügen, die mir geholfen hat. Wenn Sie nur einen Cron-Job ausführen möchten, ohne eine Datei zu beenden, sind Sie versucht, && tail -f /var/log/cron.logden Befehl einfach aus dem Cron-Befehl zu entfernen .

Dies führt jedoch dazu, dass der Docker-Container kurz nach der Ausführung beendet wird, da Docker nach Abschluss des Befehls cron denkt, dass der letzte Befehl beendet wurde, und daher den Container beendet. Dies kann vermieden werden, indem cron im Vordergrund über ausgeführt wird cron -f.

Vanugrah
quelle
9

Dies zielt zwar darauf ab, Jobs neben einem laufenden Prozess in einem Container über die Docker- execOberfläche auszuführen , dies kann jedoch für Sie von Interesse sein.

Ich habe einen Daemon geschrieben, der Container beobachtet und Jobs plant, die in ihren Metadaten definiert sind. Beispiel:

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

Eine "klassische", Cron-ähnliche Konfiguration ist ebenfalls möglich.

Hier sind die Dokumente , hier ist das Image-Repository .

Funky-Zukunft
quelle
Danke dir. Diese Antwort ist für die Docker-Container-Umgebung am besten geeignet. Keine Änderungen an Docker-Images, nur Hinzufügen eines speziellen Containers zum Ausführen von Aufgaben. Es funktioniert wie ein Befehl docker exec <container_name> <some_command>nach Zeitplan.
PRIHLOP
Dies ist die sauberste und einfachste Antwort "Erledige die Arbeit".
Ibrahim Awad
9

Ich habe ein Docker-Image basierend auf den anderen Antworten erstellt, das wie folgt verwendet werden kann

docker run -v "/path/to/cron:/etc/cron.d/crontab" gaafar/cron

Dabei gilt /path/to/cronFolgendes: absoluter Pfad zur Crontab-Datei, oder Sie können ihn als Basis in einer Docker-Datei verwenden:

FROM gaafar/cron

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

# Add your commands here

Als Referenz ist das Bild hier .

Gafi
quelle
Interessantes Bild. +1
VonC
5

Beachten Sie beim Bereitstellen Ihres Containers auf einem anderen Host, dass keine Prozesse automatisch gestartet werden. Sie müssen sicherstellen, dass der Cron-Dienst in Ihrem Container ausgeführt wird. In unserem Fall verwende ich Supervisord mit anderen Diensten, um den Cron-Dienst zu starten.

[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
quelle
Ich bekomme in Supervisor.log die Fehlermeldung, dass der Cron-Dienst mehrmals gestoppt und in den Status FATAL versetzt wurde. Cron scheint jedoch oben zu laufen und Cronjobs normal auszuführen. Danke dafür!
Lephleg
Ja, das gleiche ist mir auch passiert, aber es funktioniert wie gewohnt, also brauchen Sie sich nicht darum zu kümmern.
Sagar Ghuge
5

Definieren Sie den Cronjob in einem dedizierten Container, der den Befehl über Docker Exec an Ihren Dienst ausführt.

Dies ist eine höhere Kohäsion und das ausgeführte Skript hat Zugriff auf die Umgebungsvariablen, die Sie für Ihren Dienst definiert haben.

#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
quelle
Ich konnte dies nicht mit Docker-Schwarm zum Laufen bringen. Erste myservice unknownFehler.
Mark Grimes
Es sollte eine Warnung über die Auswirkungen einer Docking-Steckdose auf die Sicherheit gegeben sein: lvh.io/posts/…
casual
4

Wenn Sie Docker für Windows verwenden, denken Sie daran, dass Sie Ihr Zeilenendformat von CRLF in LF (dh von dos auf unix) ändern müssen, wenn Sie Ihre Crontab-Datei aus Windows in Ihren Ubuntu-Container importieren möchten. Wenn nicht, funktioniert Ihr Cron-Job nicht. Hier ist ein Arbeitsbeispiel:

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

Ich habe tatsächlich Stunden gebraucht, um das herauszufinden, da das Debuggen von Cron-Jobs in Docker-Containern eine mühsame Aufgabe ist. Hoffe, es hilft allen anderen da draußen, die ihren Code nicht zum Laufen bringen können!

Andreas Forslöw
quelle
3

Aus den obigen Beispielen habe ich diese Kombination erstellt:

Alpine Image & Edit mit Crontab in Nano (ich hasse 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
quelle
2

Richten Sie einen Cron parallel zu einem einmaligen Job ein

Erstellen Sie eine Skriptdatei, z. B. run.sh, mit dem Job, der regelmäßig ausgeführt werden soll.

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

Speichern und schließen.

Verwenden Sie Entrypoint anstelle von CMD

Wenn Sie während der Docker-Containerisierung mehrere Jobs starten müssen, verwenden Sie die Entrypoint-Datei, um alle Jobs auszuführen.

Die Einstiegspunktdatei ist eine Skriptdatei, die ausgeführt wird, wenn ein Docker-Ausführungsbefehl ausgegeben wird. Alle Schritte, die wir ausführen möchten, können in diese Skriptdatei eingefügt werden.

Zum Beispiel müssen wir 2 Jobs ausführen:

Einmal Job ausführen: Echo "Docker-Container wurde gestartet"

Führen Sie einen regelmäßigen Job aus : run.sh.

Erstellen Sie 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

Lassen Sie uns die Crontab verstehen, die in der Datei eingerichtet wurde

* * * * *: Cron Zeitplan; Der Job muss jede Minute ausgeführt werden. Sie können den Zeitplan entsprechend Ihren Anforderungen aktualisieren.

/run.sh: Der Pfad zur Skriptdatei, die regelmäßig ausgeführt werden soll

/var/log/cron.log: Der Dateiname zum Speichern der Ausgabe des geplanten Cron-Jobs.

2>&1: Die Fehlerprotokolle (falls vorhanden) werden ebenfalls in dieselbe Ausgabedatei umgeleitet, die oben verwendet wurde.

Hinweis : Vergessen Sie nicht, eine zusätzliche neue Zeile hinzuzufügen, da dies eine gültige Cron macht. Scheduler.txt: Das komplette Cron-Setup wird in eine Datei umgeleitet.

Verwenden system- / benutzerspezifischer Umgebungsvariablen in cron

Mein eigentlicher Cron-Job erwartete die meisten Argumente, da die Umgebungsvariablen an den Docker-Befehl run übergeben wurden. Mit bash konnte ich jedoch keine der Umgebungsvariablen verwenden, die zum System oder zum Docker-Container gehören.

Dann kam dies als Umgehung für dieses Problem:

  1. Fügen Sie die folgende Zeile in die Datei entrypoint.sh ein
declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env
  1. Aktualisieren Sie das Cron-Setup und geben Sie Folgendes an:
SHELL=/bin/bash
BASH_ENV=/container.env

Endlich entrypoint.shsolltest du so aussehen

#!/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

Last but not least: Erstellen Sie eine Docker-Datei

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

Das ist es. Erstellen Sie das Docker-Image und führen Sie es aus!

himanshuIIITian
quelle
1
@himanshuIIITian Ich habe es versucht, das Problem ist, dass das Skript des "einmal ausführen" -Jobs niemals zurückkehrt und auch der Mais -f nicht zurückkehrt, also ... funktioniert das nicht für mich, irgendwelche Ideen? danke
Doron Levi
@DoronLevi - können Sie bitte einige Protokolle freigeben, um das Problem zu untersuchen? Oder Sie können den gesamten Code von hier aus überprüfen - github.com/nehabhardwaj01/docker-cron
himanshuIIITian
Danke für die Rückmeldung. Ich bin froh, dass die Antwort hilfreich war.
himanshuIIITian
1

Cron-Jobs werden in / var / spool / cron / crontabs gespeichert (gemeinsamer Platz in allen mir bekannten Distributionen). Übrigens, Sie können eine Cron-Registerkarte in Bash mit so etwas erstellen:

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

Dadurch wird eine temporäre Datei mit cron task erstellt und anschließend mit crontab programmiert. Letzte Zeile temporäre Datei entfernen.

Jesus Segnini
quelle
Der cronDaemon wird normalerweise nicht in einem Container ausgeführt.
Matt
@BhargavNanekalva Es muss speziell in einem Container eingerichtet werden, den diese Antwort nicht anspricht.
Matt
@Matt, können Sie bitte darauf hinweisen, wie genau es im Container angegeben werden soll? . Ich mache crontab -l und der Befehl wird angezeigt - kagda.ru/i/6d014816d43_29-06-2017-11:38:59_6d01.png, wird aber immer noch nicht ausgeführt
Tebe
@ Копать_Шо_я_нашел Sie müssen crondzusätzlich zu dem Dienst, den Sie im Container ausführen , normalerweise mit einem Dienstmanager wie s6 ausgeführt werden. Stellen Sie das wahrscheinlich als Frage, um eine richtige Antwort zu erhalten
Matt
1

Wenn ich auf einigen abgespeckten Bildern laufen wollte, die den Root-Zugriff einschränken, musste ich meinen Benutzer zu den Sudoern hinzufügen und als ausführen 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

Vielleicht hilft das jemandem

Senica Gonzalez
quelle
Ich glaube, das Knotenbild verwendet den Knotenbenutzer. Vielleicht mussten Sie Berechtigungen für diesen Benutzer hinzufügen
bozdoz
1

Mein Problem war also dasselbe. Das Update bestand darin, den Befehlsabschnitt in der zu ändern docker-compose.yml.

Von

Befehl: crontab / etc / crontab && tail -f / etc / crontab

Zu

Befehl: crontab / etc / crontab

Befehl: tail -f / etc / crontab

Das Problem war das '&&' zwischen den Befehlen. Nach dem Löschen war alles in Ordnung.

Di Santi
quelle
-1

Die robusteste Methode, die ich bisher gefunden habe, ist das Ausführen eines unabhängigen Cron-Containers. Installieren Sie den Docker-Client und binden Sie die Docker-Socke, damit Sie mit dem Docker-Server auf dem Host kommunizieren können.

Verwenden Sie dann einfach env vars für jeden Cron-Job und ein Einstiegspunkt-Skript, um die Datei / etc / crontab zu generieren

Hier ist ein Bild, das ich nach diesem Prinzip erstellt und in den letzten 3-4 Jahren in der Produktion verwendet habe.

https://www.vip-consult.solutions/post/better-docker-cron#content

Krasi Georgiev
quelle
Die Antworten sollten in sich geschlossen sein und nicht mit externen Ressourcen verknüpft sein
Nicolas Bouliane,
-2

Versuchen Sie, Aufgaben mit einem Uhrwerk zu planen. Befolgen Sie die Schritte in diesem Link.

http://fuzzyblog.io/blog/rails/2017/05/11/adding-cron-to-a-dockerized-rails-application-using-clockwork.html

Sie können die Rake-Task in der Datei lib / clock.rb wie folgt aufrufen.

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

Erstellen Sie einen separaten Container in der Docker-Compose-Datei und führen Sie den folgenden Befehl im Container aus.

command: bundle exec clockwork lib/clock.rb
Shobha Deepak
quelle
1
Gute Idee, ein anderes Tool für die Planung zu verwenden. Diese Frage wurde jedoch speziell für cron gestellt, sodass Ihr Vorschlag meiner Meinung nach besser als Kommentar zu der Frage geeignet wäre.
Richard Kiefer