Как запустить задание cron внутри контейнера docker?
Я пытаюсь запустить cronjob внутри контейнера docker, который вызывает сценарий оболочки.
вчера я искал по всему интернету и переполнения стека, но я не мог действительно найти решение, которое работает.
Как я могу это сделать?
EDIT:
Я создал (комментируется) репозиторий github С рабочим контейнером docker cron, который вызывает сценарий оболочки с заданным интервалом.
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 [email protected] 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 "передний план")"настройки в Ubuntucron -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 с полной документацией:
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 cronFROM 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
Comments