2

I would like to run an initiator script and a cron job to run an updater script, both are in a Docker container that has a connection to the mongo database. Could someone help me how to run the cron job in the background inside the docker-entrypoint.sh file?

My docker-entrypoint.sh looks like this:

#!/usr/bin/env bash

set -m

cron & (
  source /venv/bin/activate
  python3 /code/FBInitializer.py
)

My Dockerfile looks like this:

FROM python:3.8.6-slim

RUN apt-get update && 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 && 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 . .

The initiator script runs, but the container stops working with the following error:

exited with code 0

Any idea?

Maykon Meneghel
  • 335
  • 6
  • 8

1 Answers1

1

You generally want to run only one process per container. This means running the main Python application in one container, and the cron daemon in a second container. It is more straightforward to override an image's CMD and since this is such a routine use case I would generally prefer CMD over ENTRYPOINT for most uses.

In this Dockerfile:

  • Remove the Python virtual environment. A Docker image already provides isolation from other Pythons and applications.
    # 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
    
  • Delete the docker-entrypoint.sh script. Instead, set the container's CMD to run the Python script. Since we've removed the virtual environment, you can just run the script as-is.
    # 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)
    
  • Run that container as normal; it will not launch the cron job.
    docker build -t my-image .
    docker run --name app-server -d -p 6000:6000 my-image
    
  • Run a second container, off the same image, but replacing its command with the cron daemon.
    docker run --name app-cron -d my-image \
      cron -f
    # (look up the right cron(8) option to not demonize)
    
David Maze
  • 130,717
  • 29
  • 175
  • 215
  • I really appreciate your reply @David Maze. I understand exactly the refactorings you suggested. I also understand that it is advisable to use a container for each application. A single detail to avoid permissions issues, use: CMD["chmod", "+x", "/code/FBInitializer.py"] – Maykon Meneghel Jun 07 '21 at 20:42
  • However, the "update" and "initialize" applications use the same structure of classes and functions, it only differs that the initiator will be executed only once and the updater will be executed with a scheduled task (every day at 6 pm, for example ). – Maykon Meneghel Jun 07 '21 at 20:44
  • Separating into two containers seems like the most obvious thing to do, but the question I would like to know in this topic is if it is possible to run cron in the background inside a docker-entrypoint.sh file? Apparently, I don't think it's possible. Thank you very much – Maykon Meneghel Jun 07 '21 at 20:44
  • 1
    There's nothing actually stopping the single main container process from launching subprocesses, but you're responsible for doing things like monitoring them if they fail and trying to figure out how to recover. In the example in the question, if the cron daemon fails, you just won't notice. – David Maze Jun 07 '21 at 23:23