Docker: Запустите Cronjob для другого контейнера

Я ищу рекомендации по запуску cronjobs для моего контейнера php fpm.

Прямо сейчас бегу:

  • Контейнер NGINX
  • Контейнер PHP FPM
  • Контейнер MySQL

Теперь я хотел бы запустить другой контейнер под названием "Cronjob Container", который выполняет скрипт в моем контейнере PHP FPM (мне нужны некоторые зависимости от PHP).

Итак, три возможных решения:

1.) Запуск собственного контейнера

Я бы с удовольствием использовал это решение!

Было бы хорошо иметь контейнер, в котором работает CRON, где я могу (каким-то образом) вызвать docker exec в моем контейнере php fpm... Или есть другой способ.

2.) Запуск CRON внутри контейнера PHP

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

3.) Запуск хостов Cron

Это было бы жестоко. Мне нужно было бы найти ProcessId и containerId заданного пути, а затем запустить docker exec. Но это более или менее мой последний путь... И я ненавижу управлять cronjobs без развертывания.

Итак, каков здесь наилучший подход?

Хорошего дня,

Бастиан

Я написал демон, который наблюдает за контейнерами и планирует на них задания, определенные в их метаданных. Это ближе всего подходит к вашему 1) решению. Пример:

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.

Вот эти доктора, вот этот хранилище изображений.

Сам Cron может быть установлен и запущен на переднем плане (cron -f), что делает его очень простым в установке в контейнере. Чтобы получить доступ к другим контейнерам, вы, скорее всего, установите docker в тот же контейнер для клиентского интерфейса командной строки (не для запуска демона). Затем, чтобы получить доступ к среде docker хоста, наиболее распространенным решением является привязка подключения сокета docker (-v /var/run/docker.sock:/var/run/docker.sock). Единственная проблема заключается в том, что вам нужно настроить gid docker внутри вашего контейнера в соответствии с gid хоста, а затем добавить пользователей внутри контейнера в группу docker.

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

Возврат к варианту B очень прост с помощью такого инструмента, как supervisord. Хотя это меньше, чем идеальный "один процесс на контейнер", это также не совсем анти-шаблон, поскольку он сохраняет весь ваш контейнер и зависимости вместе и устраняет любые угрозы безопасности для хоста.

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

Запустите cron в другом контейнере или даже на хосте, но запустите скрипт через php-fpm (например. cron будет "сворачиваться" или что-то в PHP-скрипте).

Убедитесь, что вы защищаете такую настройку с помощью токена безопасности, сетевых ограничений и т.д. Улучшением может быть наличие отдельного пула php-fpm с динамическими процессами, который способен порождать максимум один процесс. Этот пул будет доступен только через cron. Это также может принести пользу его собственным индивидуальным настройкам, таким как большее время выполнения, больше или меньше памяти и т.д.

P.S.: Вы можете использовать что-то вроде этот чтобы вызвать скрипт непосредственно в контейнере FPM, а не проходить через nginx.

Рассуждения: Вы, вероятно, хотите получить доступ к тем же библиотекам, той же конфигурации и т.д. Запуск процесса, случайно созданного и не контролируемого менеджером сигналов в Docker, - действительно плохая идея.

Я пытался добиться чего-то подобного.

Моя первоначальная идея состояла в том, чтобы запускать задания cron из отдельных cron контейнер и фактически выполняйте их в другом контейнере (php)то есть. чтобы иметь один crontab запись для каждого docker run -i t $containerName $scriptName ... команда, выполняющая другой сценарий внутри php контейнер

Этот подход на самом деле не очень хорош из-за недостатков @BMitch также упоминает. Кроме того, мне не очень нравится устанавливать docker к контейнеру.

Я хотел бы предложить другое решение, подходящее под ваши #1 категория: можно запустить php-fpm непосредственно. Хотя это не самое элегантное решение в мире, оно обладает преимуществами:

  1. Безопасность - никакого специального или привилегированного доступа, просто используйте хост и порт (например php-host:9000) , который уже открыт для nginx из виртуальной сети docker
  2. Имеющий cron управление отделено от php контейнер - так что масштабирование не пострадает
  3. Фактически используя cron для клановых задач - просто посадите crontab и будет сделано вместо переопределения cron с помощью различных других библиотек
  4. Выполнение скрипта не выполняется nginx, поэтому никто не может запускать их напрямую через веб-сервер, вам не нужно внедрять какие-либо механизмы аутентификации или подобные механизмы
  5. Еще меньше проблем с разрешениями. Моя предыдущая докеризация cron имела cron установленный в другом php контейнер и совместное использование кодовой базы с использованием томов. Это было эффективно, но с разрешениями нужно было обращаться осторожно, как с кэшами, DI, журналами и т.д. должен был быть доступен и доступен для записи как веб-сервером, так и cron пользователь. Такой подход устраняет проблему

Единственным недостатком, с которым я столкнулся до сих пор, является то, что первая строка w / hashbang (#!/usr/local/bin/php) рассматривается как фактический вывод, и выдается предупреждение PHP об уже отправленных заголовках (Cannot modify header information - headers already sent by ...) - удаление hashbang исправляет это.

Как на самом деле это сделать?

  1. Иметь чистый контейнер, например alpine:3.7
  2. Устанавливать apk-cron и fcgi (информация о пакете)
  3. Запустите что-то вроде:
SCRIPT_FILENAME=/docroot/scripts/cron/example-script.php \REQUEST_METHOD=GET \cgi-fcgi -bind -connect php-fpm:9000

из crontab.

Более подробная информация по теме: Прямое подключение к PHP-FPM

Я сделал это (с помощью Docker Compose более или менее автоматически), но как бы вы запустили какой-то Cronjob на основе PHP просто с помощью какой-то сетевой команды? Если я использую порт 80, у меня есть обычный тайм-аут PHP, работающий против меня, что не имеет никакого смысла… Не уверен, что было бы хорошим решением!

Не то, чтобы я что-то из этого понимаю или могу протестировать, но в этом документе есть пример, в котором говорится, что вы можете выполнить такую команду, как “docker run --rm --name web2 --link db:db training / webapp commandname”, так что, если это сработает для вас, запустите cron в одном контейнере, и пусть он выдает подобные команды на другом контейнере (контейнерах).

#1! - Извините, я действительно не знаю. Разве смысл контейнеров не в том, чтобы они были “содержимыми”? Например, “безопасный”? Я не использую docker или контейнеры приложений, поэтому я точно не знаю, о чем говорю…

Вы совершенно правы, они должны быть “сдержаны”, но вам нужно, чтобы некоторые из них работали вместе как единое программное обеспечение. Если вы не можете запускать свое программное обеспечение как единый процесс (и, честно говоря, как только вы не являетесь профессионалом в написании собственной базы данных с нуля, вы не сможете), вам нужно несколько контейнеров для совместной работы. И я не знаю, как запускать Cronjobs с ними =/.

Обмен данными между контейнерами (связывание или создание сети): Redirecting…