#docker #cron #docker-entrypoint
Вопрос:
Я хотел бы запустить сценарий инициатора и задание cron для запуска сценария обновления, оба находятся в контейнере Docker, который подключен к базе данных mongo. Может ли кто-нибудь помочь мне, как запустить задание cron в фоновом режиме внутри docker-entrypoint.sh досье?
Мой docker-entrypoint.sh выглядит так:
#!/usr/bin/env bash
set -m
cron amp; (
source /venv/bin/activate
python3 /code/FBInitializer.py
)
Мой док-файл выглядит так:
FROM python:3.8.6-slim
RUN apt-get update amp;amp; apt-get -y install python3 cron vim
RUN pip3 install --upgrade pip
COPY . /code
WORKDIR /code
COPY requirements.txt .
RUN python3 -m venv /venv
RUN . /venv/bin/activate amp;amp; pip3 install -r requirements.txt
ADD crontab /etc/cron.d/
ADD FBInitializer.py /code
ADD FBUpdater.py /code
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
RUN chmod 0644 crontab
# RUN chmod 777 ./venv/lib/python3.8/site-packages
# RUN chmod 755 ./venv/bin/activate
#RUN crontab crontab
#CMD ["cron"]
COPY /docker-entrypoint.sh /docker-entrypoint.sh
RUN ["chmod", " x", "/docker-entrypoint.sh"]
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 6000
COPY . .
Сценарий инициатора запускается, но контейнер перестает работать со следующей ошибкой:
exited with code 0
Есть идеи?
Ответ №1:
Как правило, вы хотите запускать только один процесс на контейнер. Это означает запуск основного приложения Python в одном контейнере, а демона cron-во втором контейнере. Более просто переопределить изображение CMD
, и, поскольку это такой обычный вариант использования, я бы предпочел CMD
ENTRYPOINT
для большинства применений.
В этом Докерфайле:
- Удалите виртуальную среду Python. Образ докера уже обеспечивает изоляцию от других питонов и приложений.
# Outright delete this line: # RUN python3 -m venv /venv # Doesn't need a virtual environment, just the "system" Python: RUN pip3 install -r requirements.txt
- Удалите
docker-entrypoint.sh
скрипт. Вместо этого установите контейнерCMD
для запуска скрипта Python. Поскольку мы удалили виртуальную среду, вы можете просто запустить скрипт как есть.# Delete: # COPY /docker-entrypoint.sh /docker-entrypoint.sh # RUN ["chmod", " x", "/docker-entrypoint.sh"] # ENTRYPOINT ["/docker-entrypoint.sh"] # Instead: CMD ["/code/FBInitializer.py"] # (That script should be executable, and begin with the usual # #!/usr/bin/env python3 # shebang line)
- Запустите этот контейнер как обычно; он не запустит задание cron.
docker build -t my-image . docker run --name app-server -d -p 6000:6000 my-image
- Запустите второй контейнер, с того же изображения, но заменив его команду демоном cron.
docker run --name app-cron -d my-image cron -f # (look up the right cron(8) option to not demonize)
Комментарии:
1. Я действительно ценю ваш ответ @David Maze. Я точно понимаю, какие рефакторинги вы предложили. Я также понимаю, что желательно использовать контейнер для каждого приложения. Одна деталь, чтобы избежать проблем с разрешениями, используйте: CMD[«chmod», » x», «/code/FBInitializer.py»]
2. Однако приложения «обновление» и «инициализация» используют одинаковую структуру классов и функций, отличается только то, что инициатор будет выполняться только один раз, а средство обновления будет выполняться с запланированной задачей (например, каждый день в 6 часов вечера ).
3. Разделение на два контейнера кажется наиболее очевидным, но вопрос, который я хотел бы знать в этой теме, заключается в том, можно ли запускать cron в фоновом режиме внутри docker-entrypoint.sh досье? Очевидно, я не думаю, что это возможно. Большое спасибо
4. На самом деле ничто не мешает одному основному контейнерному процессу запускать подпроцессы, но вы несете ответственность за такие действия, как мониторинг их в случае сбоя и попытка выяснить, как восстановить. В примере, приведенном в вопросе, если демон cron выйдет из строя, вы просто не заметите.