Run the cron job in the background inside the docker-entrypoint.sh file

Viewed 1614

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?

1 Answers

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)
    
Related