Запустите задание cron в фоновом режиме внутри docker-entrypoint.sh файл

#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 выйдет из строя, вы просто не заметите.