Как настроить cron в окружении, где используются Docker и php-fpm?

Прошло значительное время, и я так и не получил удовлетворительного ответа на свой вопрос. Я изучил множество статей, но в комментариях, как правило, лишь холивары. Все обсуждают принципы работы Docker, но это не помогает понять практические аспекты. У кого-нибудь был подобный опыт? Как вы настраивали эту интеграцию? <br/><br/> На мой взгляд, есть несколько вариантов: можно поместить cron в контейнер с приложением и позволить ему работать там, либо разделить приложение на два контейнера — один для обработки запросов, а другой для выполнения фоновых задач с помощью cron. Идея держать cron на хосте и запускать команды для контейнера вызывает у меня недоумение.
  • 6 февраля 2025 г. 13:04
Ответы на вопрос 3
Настройка cron в окружении с Docker и PHP-FPM может быть немного запутанной, особенно если вы новичок в работе с контейнерами. Вот несколько подходов, которые вы можете рассмотреть:

### 1. Cron в том же контейнере, что и PHP-FPM

Этот метод подходит для простых приложений или если у вас нет строгих требований по изоляции процессов. Чтобы настроить cron в контейнере с PHP-FPM, вам необходимо создать пользовательский Docker-образ, который будет содержать и PHP-FPM, и cron.

**Пример Dockerfile:**

```Dockerfile
FROM php:7.4-fpm

# Устанавливаем cron и необходимые утилиты
RUN apt-get update && apt-get install -y cron

# Копируем файл cron в контейнер
COPY ./cron/my_cron_file /etc/cron.d/my_cron_file

# Применяем права
RUN chmod 0644 /etc/cron.d/my_cron_file

# Устанавливаем cron
RUN crontab /etc/cron.d/my_cron_file

# Создаем видимость для вывода логов
RUN touch /var/log/cron.log

# Запускаем cron и php-fpm
CMD cron && php-fpm
```

**Файл cron (my_cron_file):**

```
* * * * * root /usr/local/bin/php /path/to/your/script.php >> /var/log/cron.log 2>&1
```

### 2. Отдельный контейнер для cron

Этот подход позволяет вам полностью изолировать выполнение фоновых задач. Вы можете создать отдельный контейнер для cron, который будет выполнять команды в другом контейнере, используя Docker CLI или Docker-compose.

**Пример Dockerfile для cron-контейнера:**

```Dockerfile
FROM php:7.4-cli

# Устанавливаем curl, если нужно
RUN apt-get update && apt-get install -y curl

# Копируем файл cron
COPY ./cron/my_cron_file /etc/cron.d/my_cron_file

# Применяем права
RUN chmod 0644 /etc/cron.d/my_cron_file

# Устанавливаем cron
RUN crontab /etc/cron.d/my_cron_file

CMD ["cron", "-f"]
```

**Файл docker-compose.yml:**

```yaml
version: '3.8'

services:
  app:
    image: your_app_image
    # другие настройки

  cron:
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      - app
```

### 3. Cron на хосте

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

```bash
* * * * * docker exec -it your_app_container /usr/local/bin/php /path/to/your/script.php
```

### Заключение

Выбор подходящего решения зависит от ваших требований и архитектуры приложения. Если вам нужна простота, первый вариант может быть лучшим решением. Если вы хотите более гибкую и чистую архитектуру, то второй вариант предпочтительнее.
Ничего дикого в кроне на хосте нету (особенно если это не крон, а systemd-таймер), как и в отдельном сервисе-планировщике. А если хотите, чтобы было прям по фэншую - юзайте Kubernetes + CronJobs.
Если честно - не понимаю смысла вопроса, вы же изучили теорию 
сделайте так, как будет удобно вам - вам же с этим жить
а вообще надо исходить из того чем занимается cron задачи - где-то, ради изоляции потребления ресурсов, лучше вынести крон во второй контейнер, а где-то вы решите запихать его внутрь контейнера приложения
По поводу запуска на хосте - сервисы контейнеризации обычно не дают доступ к хосту
Похожие вопросы