- Вопрос или проблема
- Ответ или решение
- Решение проблемы выполнения команд Makefile в cronjob под Docker на Fedora Server
- 1. Проверка структуры Makefile
- 2. Путь к Makefile и рабочая директория
- 3. Проверка прав доступа
- 4. Запуск cron с отладкой
- 5. Переменные окружения
- 6. Альтернативный способ работы с файлами
- Заключение
Вопрос или проблема
Я создаю несколько крон-задач, которые используют команду “make” для выполнения скриптов на python. Эти крон-задачи выполняются внутри контейнера Docker. Я могу запускать свои крон-задачи с помощью команды make внутри своего контейнера, когда использую Docker Desktop на своем ноутбуке с Windows, и команды вроде * * * * * cd /code && make help
возвращают ожидаемый вывод, который является эхо-выводом всех доступных команд make для моего проекта. Я протестировал эти крон-задачи и на Mac, где они также сработали. Однако, когда я пытаюсь запустить ту же крон-задачу на ноутбуке с Linux, работающем на “Fedora Server”, у меня не получается заставить “make” работать правильно (это физический компьютер, а не виртуальная машина).
Крон-задачи запускаются из директории “/etc/crontabs/root” внутри контейнера. Крон-задача * * * * * cd /code && make help
, выполняемая внутри моего контейнера Docker на установке Linux, дает ответ crond: USER root pid 132 cmd cd /code && make help '. Stop. No rule to make target 'help
.
Основные крон-задачи, такие как * * * * * echo 'Hello world'
, выводят ожидаемый ответ на обеих машинах. Я также могу вручную запускать команды make на любом компьютере в директории “/code”, такие как make help
.
Я экспортирую папку проекта с ноутбука с Windows в директорию “notroot@localhost:~/compose”, которая принадлежит непользователю root на моем ноутбуке с Linux, используя клиент FileZilla (любые советы по лучшим способам это сделать будут очень приветствоваться). Я использую “docker compose” для создания и запуска своих контейнеров из директории “notroot@localhost:~/compose/xcron”.
Структура моего проекта выглядит следующим образом:
/xcron
- .env
- requirements.txt
- Makefile
- /api
- /spotify
- ...
- /leetcode
- ...
- ...
Мой файл compose, docker-compose.yml:
services:
xcron-app:
container_name: xcronapp
restart: always
build: .
networks:
- xcron_db_network
- xcron_web_network
volumes:
- xcronvol:/code
db:
container_name: xcronpostgres
image: postgres
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_NAME}
volumes:
- postgresvolume:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME} -d ${DB_NAME}"]
interval: 10s
retries: 5
start_period: 30s
timeout: 10s
networks:
- xcron_db_network
networks:
xcron_db_network:
driver: bridge
xcron_web_network:
driver: bridge
volumes:
xcronvol:
postgresvolume:
Dockerfile, используемый в моем проекте, представлен ниже. Есть некоторые файлы, которые не копируются из проектных файлов, такие как папка python venv, которая никогда не предназначалась для использования внутри контейнеров. Dockerfile:
FROM alpine:latest
COPY config/cronjobs /etc/crontabs/root
COPY requirements.txt /etc/requirements/requirements.txt
ENV PYTHONUNBUFFERED=1
RUN apk add --update --no-cache python3 py3-pip make bash util-linux vim && ln -sf python3 /usr/bin/python
COPY .env /code/.env
COPY api /code/api
COPY auth /code/auth
COPY migrations/down /code/migrations/down
COPY migrations/up /code/migrations/up
COPY migrations/down.py /code/migrations/down.py
COPY migrations/up.py /code/migrations/up.py
COPY tweets /code/tweets
COPY Makefile /code/Makefile
RUN python3 -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN pip install -r /etc/requirements/requirements.txt
RUN chmod 777 /etc/crontabs/root
WORKDIR /code
CMD ["crond", "-f", "-d", "8"]
После запуска ‘docker compose up’, мои файлы внутри контейнера Docker структурированы так же, как и раньше (за исключением файлов, которые были проигнорированы в Dockerfile), но базовая папка теперь называется “code”.
/code
- .env
- Makefile
- /api
- /spotify
- ...
- /leetcode
- ...
- ...
Я пробовал добавлять права доступа внутри моего контейнера Docker к моим файлам, используя chmod 777 <имя_файла>
на моем “code/Makefile”, “code/.env” файле, “/etc/crontabs/root”. Я пробовал изменять мою крон-задачу с абсолютными путями, такими как /usr/bin/make -C /code help
“, а также множество вариаций флагов “-C” и “-f”. Я пробовал запускать команды в своей рабочей директории cd /code && make -f /code/Makefile help
и выходить из “root”, откуда, как я полагал, запускались мои крон-задачи cd .. && make -f /code/Makefile -C /code help
.
Я пытался запускать крон-задачи через bash явно /bin/bash -c 'cd /code && make help'
.
Результаты вывода этих крон-задач остаются прежними crond: USER root pid 123 cmd /usr/bin/make -C /code help '. Stop. No rule to make target 'help
.
Ответ или решение
Решение проблемы выполнения команд Makefile в cronjob под Docker на Fedora Server
Ваша ситуация иллюстрирует распространённую проблему при работе с cronjob и Docker, особенно в контексте различий между ОС. Вы описали, что команда make help
работает безупречно в Docker на Windows и macOS, но выдаёт ошибку при выполнении на Fedora Server. Давайте разберемся, в чём может быть причина и как это можно исправить.
1. Проверка структуры Makefile
Первым делом убедитесь, что ваш Makefile действительно содержит цель help
. Для этого откройте Makefile и проверьте наличие следующей записи:
help:
@echo "Available commands:"
@echo " help"
...
Затем попробуйте выполнить команду make help
вручную внутри вашего Docker-контейнера, чтобы убедиться, что всё работает правильно.
2. Путь к Makefile и рабочая директория
Проблема может быть связана с тем, как cron выполнит команды. Cron запускает команды в чистом окружении, и это может повлиять на то, где и как он ищет ваш Makefile. Убедитесь, что вы используете абсолютный путь к Makefile, а также укажите полный путь к директории /code
.
Попробуйте изменить вашу строку cron на:
* * * * * cd /code && /usr/bin/make -f /code/Makefile help
Также можете использовать флаг -C
:
* * * * * /usr/bin/make -C /code help
3. Проверка прав доступа
Проверьте, что все файлы и директории имеют необходимые права доступа. Вы уже применили chmod 777
, но важно убедиться, что эта команда была выполнена успешно. Также проверьте, не происходит ли сбой из-за ограничений SELinux, который может блокировать доступ к файлам.
4. Запуск cron с отладкой
Для более детальной отладки запустите cron с увеличенной степенью детальности. В вашем Dockerfile
вы уже указали уровень отладки -d 8
, однако полезно потом проверить логи cron для получения информации о возможных ошибках. Например, выполните команду:
docker logs xcronapp
Это позволит вам увидеть любые ошибки, возникающие при выполнении cron job’ов.
5. Переменные окружения
Обратите внимание, что cron может не передавать переменные окружения, установленные в вашем контейнере. Если ваш Makefile полагается на какие-либо переменные окружения, это может вызвать проблему. Убедитесь, что все необходимые переменные окружения определены непосредственно в командной строке или в скрипте, который вызывает make
.
6. Альтернативный способ работы с файлами
Если вы считаете, что использование FileZilla для передачи файлов не оптимально, вы можете использовать команду rsync
для более быстрых и эффективных операций.
rsync -avz /path/to/source/ user@destination:/path/to/target/
Это может сократить время передачи и гарантировать целостность данных при перемещении файлов между системами.
Заключение
Следуя данным рекомендациям, вы сможете устранить проблему с выполнением команд Makefile в ваших cronjob под Docker на Fedora Server. Изучите структуру Makefile, убедитесь в корректности путей, проверьте права доступа и исследуйте логи для диагностики. Старайтесь поддерживать порядок в ваших cronjob’ах, используя явные пути и необходимые переменные окружения. Удачи в вашей работе!