Running Cron Jobs in Docker Containers
In this tutorial, you will learn about Running Cron Jobs in Docker Containers. We cover key concepts, practical examples, and best practices to help you master this topic.
Run cron jobs inside Docker containers: install cron, create crontabs, handle logging, manage environment variables, and use supervisord or entrypoint patterns for scheduling.
What You Learn
You will learn how to run cron inside Docker containers, handle the single-Process-per-container paradigm, use supervisord for multi-process containers, configure logging in Docker, and manage environment variables for cron in containers.
Why It Matters
Docker containers typically run a single process. Cron introduces a second process (the cron daemon) that must be managed alongside your application. Understanding how to combine them is essential for containerized backend systems.
Real-World Use
DodaTech runs scheduled tasks in Docker containers: hourly database health checks, daily log rotation, and weekly report generation. Each container runs both the application server and cron, with supervisord managing both processes.
Basic Cron in Docker
# Dockerfile
FROM ubuntu:22.04
# Install cron
RUN apt-get update && apt-get install -y cron
# Create crontab file
RUN echo "0 3 * * * /usr/local/bin/backup.sh >> /var/log/cron/backup.log 2>&1" > /etc/cron.d/my-cron \
&& echo "*/30 * * * * /usr/local/bin/health.sh >> /var/log/cron/health.log 2>&1" >> /etc/cron.d/my-cron
# Set permissions and apply crontab
RUN chmod 0644 /etc/cron.d/my-cron && crontab /etc/cron.d/my-cron
# Copy scripts
COPY backup.sh /usr/local/bin/backup.sh
COPY health.sh /usr/local/bin/health.sh
RUN chmod +x /usr/local/bin/backup.sh /usr/local/bin/health.sh
# Start cron and keep container running
CMD cron -f
# Build and run
docker build -t cron-app .
docker run -d --name cron-container cron-app
# Check logs
docker exec cron-container tail -f /var/log/cron/backup.log
# Verify cron is running
docker exec cron-container ps aux | grep cron
Using Supervisord
# Dockerfile with supervisord
FROM python:3.11-slim
# Install cron and supervisor
RUN apt-get update && apt-get install -y cron supervisor
# Create supervisor config
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Create crontab
COPY crontab /etc/cron.d/app-cron
RUN chmod 0644 /etc/cron.d/app-cron && crontab /etc/cron.d/app-cron
# Copy application
COPY app/ /app/
WORKDIR /app
# Start supervisord
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
; supervisord.conf
[supervisord]
nodaemon=true
logfile=/var/log/supervisor/supervisord.log
pidfile=/tmp/supervisord.pid
[program:cron]
command=/usr/sbin/cron -f
autostart=true
autorestart=true
stdout_logfile=/var/log/cron/crond.log
stderr_logfile=/var/log/cron/crond.err
[program:app]
command=/usr/local/bin/python app.py
autostart=true
autorestart=true
stdout_logfile=/var/log/app/app.log
stderr_logfile=/var/log/app/app.err
Entrypoint Pattern
#!/bin/bash
# entrypoint.sh
# Start cron and the main application
# Run startup tasks
echo "Running startup checks..."
/usr/local/bin/startup.sh
# Setup cron jobs
echo "Setting up cron..."
printenv | grep -v "no_proxy\|HOME\|PWD\|SHLVL" > /etc/environment
cron
# Start main application
echo "Starting main application..."
exec "$@"
# Dockerfile using entrypoint pattern
FROM python:3.11-slim
RUN apt-get update && apt-get install -y cron
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
COPY crontab /etc/cron.d/app-cron
RUN chmod 0644 /etc/cron.d/app-cron
COPY app/ /app/
WORKDIR /app
ENTRYPOINT ["/entrypoint.sh"]
CMD ["python3", "main.py"]
Handling Environment Variables
#!/bin/bash
# /usr/local/bin/cron-env.sh
# Cron in Docker has minimal environment.
# This script loads environment variables for cron jobs.
# Load environment from file
if [ -f /etc/environment ]; then
export $(cat /etc/environment | xargs)
fi
# Load additional config
if [ -f /app/.env ]; then
export $(cat /app/.env | xargs)
fi
# Now run the actual command
exec "$@"
# Dockerfile with environment handling
FROM python:3.11-slim
RUN apt-get update && apt-get install -y cron
# Copy environment loader
COPY cron-env.sh /usr/local/bin/cron-env.sh
RUN chmod +x /usr/local/bin/cron-env.sh
# Use environment loader in crontab
RUN echo "0 3 * * * /usr/local/bin/cron-env.sh /usr/local/bin/backup.sh >> /var/log/cron/backup.log 2>&1" > /etc/cron.d/app-cron
# Set environment in Docker
ENV DB_HOST=localhost
ENV DB_USER=app
ENV APP_ENV=production
Logging in Docker Cron
#!/bin/bash
# /usr/local/bin/cron-logger.sh
# Wrapper that logs to stdout for Docker's log system
JOB_NAME="$1"
shift
echo "[$(date '+%Y-%m-%d %H:%M:%S')] START: ${JOB_NAME}"
# Execute the actual command
"$@" 2>&1
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] END: ${JOB_NAME} (success)"
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] FAIL: ${JOB_NAME} (exit: ${EXIT_CODE})"
fi
exit $EXIT_CODE
# Using the logger wrapper
COPY cron-logger.sh /usr/local/bin/cron-logger.sh
RUN chmod +x /usr/local/bin/cron-logger.sh
# Crontab entry using logger wrapper
RUN echo "0 3 * * * /usr/local/bin/cron-logger.sh backup /usr/local/bin/backup.sh" > /etc/cron.d/app-cron
Docker Compose with Cron
# docker-compose.yml
version: '3.8'
services:
app:
build: .
container_name: app-with-cron
environment:
- DB_HOST=postgres
- DB_USER=app
- APP_ENV=production
- TZ=UTC
volumes:
- cron-logs:/var/log/cron
- backups:/backups
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
postgres:
image: postgres:15
environment:
POSTGRES_DB: app
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
volumes:
cron-logs:
backups:
Common Mistakes
1. Container Exits Immediately
Cron runs in the background by default. Without cron -f (foreground), the container exits immediately after starting cron.
2. Missing Environment Variables
Docker cron lacks environment variables set in the Dockerfile. Write them to /etc/environment or source them in cron wrappers.
3. Using @reboot in Container Cron
@reboot runs when cron starts, but container restarts are common. Use @reboot with caution in Docker. Some minimal images do not support it.
4. No Logging to stdout
Container logs come from stdout/stderr. Cron logs to files by default. Send cron output to stdout for visibility in docker logs.
5. Timezone Mismatch
Containers default to UTC. If your cron jobs expect a different timezone, set TZ environment variable or configure timezone in the Dockerfile.
Practice Questions
1. Why does a cron Docker container exit immediately?
Cron forks to the background by default. Without cron -f to run in the foreground, the container sees the main process exit and stops.
2. How do you run multiple processes in a Docker container?
Use supervisord or a similar process manager to run cron and your application as separate managed processes within one container.
3. How do cron jobs access Docker environment variables?
Write environment variables to /etc/environment in the entrypoint, then source them in cron wrappers. Or pass them explicitly in the crontab.
4. How do you view cron logs in Docker?
Redirect cron output to stdout: cron-job.sh >> /proc/1/fd/1 2>&1 or use a wrapper that logs to stdout for docker logs.
Challenge
Build a Docker image that runs: a web application server, cron daemon for scheduled tasks, daily backup at 3 AM to /backups, health check every 5 minutes logging to stdout, log rotation daily via cron, and uses supervisord for process management.
FAQ
Mini Project: Docker Cron Container
# Dockerfile
FROM alpine:3.18
# Install cron and bash
RUN apk add --no-cache dcron bash
# Create log directory
RUN mkdir -p /var/log/cron /scripts
# Copy scripts
COPY scripts/ /scripts/
RUN chmod +x /scripts/*.sh
# Setup crontab (using BusyBox crond format)
RUN echo "*/5 * * * * /scripts/health.sh >> /var/log/cron/health.log 2>&1" > /var/spool/cron/crontabs/root \
&& echo "0 3 * * * /scripts/backup.sh >> /var/log/cron/backup.log 2>&1" >> /var/spool/cron/crontabs/root
# Write env for cron
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["crond", "-f", "-l", "2"]
#!/bin/sh
# entrypoint.sh
echo "Setting up environment for cron..."
printenv > /etc/environment
echo "Starting cron..."
exec "$@"
What's Next
Now that you understand cron in Docker, explore cron in Kubernetes for cluster-level scheduling, then learn about cron alternatives like systemd timers.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro