7👍
A Docker container only runs one process. You need to run two separate things: the main application server, and (after some initial setup) the cron daemon. You can straightforwardly run two separate containers running two separate commands from the same image, with the correct setup.
The first change I would make here is to combine what you currently have as a split ENTRYPOINT
and CMD
into a single CMD
:
# no ENTRYPOINT, but
CMD ["python3", "manage.py", "runserver", "0.0.0.0:8080"]
With this setup, you can launch one container using this default command, and a second command from the same image but overriding command:
in the Compose setup.
version: '3.8'
services:
db: { ... }
webapp:
build: ./back
restart: unless-stopped
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- db
# run the default command: from the image; no override
# skip unnecessary links:, container_name:, volumes: options
cron:
build: ./back # same as main application
restart: unless-stopped
env_file:
- .env
depends_on:
- db
command: cron -f # as a long-running foreground process
The thing we haven’t done here is populate the crontab at container startup. This is where ENTRYPOINT
can come in: if you have an ENTRYPOINT
, it gets run instead of the CMD
, but it gets passed the CMD
as arguments. A pretty typical pattern here is to use ENTRYPOINT
for a shell script that does some first-time setup, and then ends with exec "$@"
to run whatever the provided CMD
/command:
was.
#!/bin/sh
# docker-entrypoint.sh
# If this is going to be a cron container, set up the crontab.
if [ "$1" = cron ]; then
./manage.py crontab add
fi
# Launch the main container command passed as arguments.
exec "$@"
Then in the Dockerfile, specify this script as the ENTRYPOINT
.
...
WORKDIR /back
COPY . ./ # including docker-entrypoint.sh
...
ENTRYPOINT ["./docker-entrypoint.sh"] # must be JSON-array syntax
CMD ["./manage.py", "runserver", "0.0.0.0:8080"] # as before
You don’t need to override entrypoint:
here. Commands like docker-compose run web app bash
to get an interactive debugging shell will work fine; they’ll go via that entrypoint script, and run the shell as the final exec "$@"
line.