Cron + Docker — what to do
2020-01-29
|
2 mins to read
|
Share article
Introduction
This guide demonstrates how to run Linux cron jobs that execute commands inside Docker containers. When I started to google this, I found two solutions right away, but both seemed problematic.
You can find the source files for this tutorial in the recipe-06 folder of this repository: https://github.com/ikknd/docker-study

Bad option 1 — build a dedicated cron container
Build a custom crontab image, copy the crontab file inside, and run commands toward other containers.
Problems:
- You must rebuild the image every time you change a cron command or add a new one.
- Making calls from the cron container to other containers can be awkward (networking, container IDs, etc.).
Bad option 2 — modify the application container to run cron
Add cron to the app container and run both cron and the original process inside the same container.
Problems:
- The container ends up running two processes (cron + the app), which goes against Docker philosophy: “one process per container”.
- Adds complexity to the app image and lifecycle.
Good option — run cron on the host
Run cron on the host machine where you start your Docker containers and use docker exec from cron to run the command inside the target container.
Example crontab line:
* * * * * docker exec -t {containerID} {command} >> /dev/null 2>&1
Concrete example (Laravel scheduler):
* * * * * docker exec -t $(docker ps -qf "name=docker_php_1") \
php artisan schedule:run >> /dev/null 2>&1
Notes and explanations:
- Normally you would run:
but container IDs can change on restart. You don't want to edit crontab every time a container restarts.docker exec -t <container_id> php artisan schedule:run - Use
$(docker ps -qf "name=<container_name>")to lookup the container ID by name:$(docker ps -qf "name=docker_php_1") - Or lookup by image ancestor:
$(docker ps -qf "ancestor=php:7.2-fpm") php artisan schedule:runis a Laravel-specific command used here as an example; replace with whatever command you need to execute inside the container.- Redirecting output to
/dev/null(>> /dev/null 2>&1) silences stdout/stderr; remove or change that redirect while debugging.
Tips
- If your host cron environment doesn't have the same
PATHor environment variables as your interactive shell, use full paths in the cron command or source an environment file first. Example using a script:
where* * * * * /usr/local/bin/run-scheduled.sh >> /var/log/cron-scheduler.log 2>&1run-scheduled.shcontains:#!/usr/bin/env bash # optional: source environment variables # . /etc/profile docker exec -t $(docker ps -qf "name=docker_php_1") \ php /var/www/html/artisan schedule:run - Ensure the host user running cron has permission to use Docker (is in the
dockergroup or runs cron under root). - For reliability, consider adding checks to the wrapper script to ensure the container exists and is running before calling
docker exec.
That's it — keeping cron on the host and using docker exec avoids rebuilding images or running multiple processes inside a container while giving you stable cron entries that locate containers by name or image.