Как запустить задание cron внутри контейнера docker?



Я пытаюсь запустить cronjob внутри контейнера docker, который вызывает сценарий оболочки.

вчера я искал по всему интернету и переполнения стека, но я не мог действительно найти решение, которое работает.
Как я могу это сделать?

EDIT:

Я создал (комментируется) репозиторий github С рабочим контейнером docker cron, который вызывает сценарий оболочки с заданным интервалом.

789   13  

13 ответов:

вы можете скопировать crontab в образ, чтобы контейнер, запущенный из указанного образа, запустил задание.

в разделе "запустите задание cron с помощью Docker" из Жюльен Буле в своем Ekito/docker-cron:

давайте создадим новый файл под названием "crontab", чтобы описать нашу работу.

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

в следующем файле DockerFile описаны все шаги по созданию вашего изображение

FROM ubuntu:latest
MAINTAINER docker@ekito.fr

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

# Add crontab file in the cron directory
ADD crontab /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

(см. Джафар ' s комментарий и как сделать apt-get установить менее шумные?:
apt-get -y install -qq --force-yes cron может работать тоже)


или убедитесь, что ваше задание перенаправлено непосредственно на stdout / stderr вместо файла журнала, как описано в hugoShaka ' s ответ:

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

заменить последнюю строку Dockerfile на

CMD ["cron", "-f"]

Смотрите также (о cron -f, что означает cron "передний план")"настройки в Ubuntu cron -f не работает"


построить и запустить его:

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

будьте терпеливы, подождите 2 минуты, и ваша командная строка должна отображать:

Hello world
Hello world

Эрик добавляет в комментариях:

отметим, что tail может не отображаться правильный файл, если он создан во время изображения строить.
Если это так, вам нужно создать или коснуться файла во время выполнения контейнера, чтобы хвост подобрал правильный файл.

в разделе "выход tail -f в конце докера CMD не показывает".

принятое решение может быть опасным в производственной среде.

в docker вы должны выполнить только один процесс на контейнер, потому что если вы этого не сделаете, процесс, который раздвоился и пошел фон, не контролируется docker и может остановиться без вашего ведома.

при использовании CMD cron && tail -f /var/log/cron.log процесс cron в основном вилка для того, чтобы выполнить cron в фоновом режиме основной процесс завершается и позволяет выполнить tailf на переднем плане. Демон cron процесс может остановиться или потерпеть неудачу вы не заметите, ваш контейнер по-прежнему будет работать беззвучно, и ваш инструмент оркестровки не перезапустит его.

вы можете избежать этого, перенаправив непосредственно команды cron, выводимые в ваш докер stdout и stderr которые расположены соответственно в /proc/1/fd/1 и /proc/1/fd/2.

используя основные команды bash вы можете сделать что-то вроде этого :

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

и ваш CMD будет :CMD ["cron", "-f"]

то, что предложил @VonC, приятно, но я предпочитаю делать всю конфигурацию заданий cron в одной строке. Это позволит избежать кросс-платформенных проблем, таких как cronjob location, и вам не нужен отдельный файл cron.

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

после запуска контейнера docker вы можете убедиться, что служба cron работает:

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

Если вы предпочитаете иметь точку входа вместо CMD, то вы можете заменить CMD выше с

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

для тех, кто хочет использовать простой и легкий образ:

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

здесь cronjobs это файл, который содержит ваши cronjobs, в этой форме:

* * * * * echo "hello stackoverflow" >> /test_file 2>&1
# remember to end this file with an empty new line

есть еще один способ сделать это, это использовать Tasker, бегун задач, который имеет поддержку cron (планировщик).

почему ? Иногда для запуска задания cron вам нужно смешать ваш базовый образ (python, java, nodejs, ruby) с crond. Это означает, что еще один образ для поддержания. Tasker избежать этого, отделив crond и вы контейнер. Вы можете просто сосредоточиться на изображении, которое вы хотите выполнить свои команды, и настроить Tasker для его использования.

теги , это будет выполнять некоторые задачи для вас
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")'

там есть 3 задачи, все они будут выполняться каждую минуту (every: minute), и каждый из них будет выполнять script код, внутри изображения, определенные в .

просто запустить docker-compose up, и посмотреть, как это работает. Вот РЕПО Tasker с полной документацией:

http://github.com/opsxcq/tasker

VonC это ответ довольно тщательно. Кроме того, я хотел бы добавить одну вещь, которая помогла мне.Если вы просто хотите запустить задание cron без хвоста файла, у вас возникнет соблазн просто удалить && tail-f /var/log/cron.вход из команды cron. Однако это приведет к выходу контейнера docker вскоре после запуска, потому что когда команда cron завершается, docker считает, что последняя команда вышла и, следовательно, убивает контейнер. Этого можно избежать, запустив cron в передний план через cron-f

Я бы написал это как комментарий, но у меня пока недостаточно очков:)

хотя это нацелено на выполнение заданий рядом с запущенным процессом в контейнере через Docker exec интерфейс, это может быть интересно для вас.

Я написал демон, который наблюдает за контейнерами и расписывает задания, определенные в их метаданных, на них. Пример:

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

"классический", cron-подобная конфигурация также возможна.

здесь docs, вот репозиторий образов.

Я создал докер изображение на основе других ответов, которые могут быть использованы как

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

здесь /path/to/cron: абсолютный путь к файлу crontab

или использовать в качестве базы в Dockerfile

FROM gaafar/cron

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

# Add your commands here

при развертывании контейнера на другом хосте, просто обратите внимание, что он не будет запускать какие-либо процессы автоматически. Вы должны убедиться, что служба хрон работает внутри вашего контейнера. В нашем случае я использую Supervisord с другими службами для запуска службы 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

определите cronjob в выделенном контейнере, который запускает команду через docker exec для вашего сервиса.

это более высокая когезия, и запущенный скрипт будет иметь доступ к переменным среды, которые вы определили для своей службы.

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

задания Cron хранятся в /var/spool/cron / crontabs (общее место во всех дистрибутивах, которые я знаю). Кстати, вы можете создать вкладку cron в bash, используя что-то вроде этого:

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

это создаст временный файл с задачей cron, а затем запрограммирует его с помощью crontab. Последняя строка удалить временный файл.

при запуске некоторых обрезанных изображений, которые ограничивают доступ root, мне пришлось добавить своего пользователя в sudoers и запустить как 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

может быть, это кому-то помогает

самый надежный способ, который я нашел до сих пор, - это запустить независимый контейнер cron-установить клиент docker и привязать монтировать носок docker, чтобы вы могли поговорить с сервером docker на хосте.

затем просто используйте env vars для каждого задания cron и сценарий entrypoint для создания /etc / crontab

    Ничего не найдено.

Добавить ответ:
Отменить.