Debugging Docker Cron Jobs: Why “rm -rf /opt/*” Cron Task Fails to Execute in Ubuntu Container


4 views

When working with cron jobs inside Docker containers, many developers encounter a common pitfall where scheduled tasks simply don't execute as expected. The specific case we're examining involves:

  • Ubuntu-based Docker container
  • Cron installed via apt-get
  • Scheduled file deletion task (* * * * * root rm -rf /opt/*)
  • Proper crontab entry visible via crontab -l
  • Yet files persist in /opt directory

Looking at the provided Dockerfile, several potential issues become apparent:

FROM ubuntu:latest
MAINTAINER docker@ekito.fr

RUN apt-get update && apt-get -y install cron

COPY ./testfiles /opt/

RUN touch /var/log/cron.log

RUN (crontab -l -u root; echo "* * * * * root rm -rf /opt/*") | crontab

CMD cron

ENTRYPOINT ["/bin/sh", "-c", "/bin/bash"]

The primary issues causing the cron job to fail are:

  1. Cron Service Management: The CMD cron starts the cron daemon, but the ENTRYPOINT overrides it with a bash shell
  2. User Specification: The crontab format with "root" before the command is incorrect for system crontabs
  3. Logging Verification: No mechanism exists to verify if cron is actually running

Here's a corrected version of the Dockerfile:

FROM ubuntu:latest

RUN apt-get update && apt-get -y install cron

COPY ./testfiles /opt/

# Create proper cron job file
RUN echo "* * * * * root rm -rf /opt/*" > /etc/cron.d/cleanup
RUN chmod 0644 /etc/cron.d/cleanup

# Create log file and ensure proper permissions
RUN touch /var/log/cron.log
RUN chmod 666 /var/log/cron.log

# Start cron and tail logs to keep container running
CMD cron && tail -f /var/log/cron.log

For more robust solutions, consider these approaches:

# Option 1: Using supervisord
FROM ubuntu:latest
RUN apt-get update && apt-get install -y cron supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD ["/usr/bin/supervisord"]

# Option 2: Using bash script wrapper
FROM ubuntu:latest
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

To confirm your cron jobs are working:

# Check cron service status
service cron status

# View cron logs
grep CRON /var/log/syslog

# Alternative log viewing
tail -f /var/log/cron.log

  • Always test cron commands manually first
  • Use absolute paths in cron jobs
  • Maintain separate log files for each job
  • Consider using dedicated cron image like alpine-cron
  • For production, use Kubernetes CronJobs instead

The Docker setup appears correct at first glance - the cron tab is properly configured and the files exist in the target directory. However, the cron job isn't executing as expected. Let's examine what's really happening.

The primary issue lies in how the cron service operates within Docker containers. Unlike traditional Linux systems, Docker containers:

1. Don't automatically start system services
2. Run with a minimal process management setup
3. Often require explicit process supervision

Several factors could be causing the cron job to fail:

  • The cron daemon isn't actually running despite the CMD instruction
  • Environment variables aren't properly passed to cron jobs
  • Permissions issues between root and the cron execution context
  • The container's default shell environment differs from cron's

Here's a corrected Dockerfile that properly handles cron execution:

FROM ubuntu:latest
RUN apt-get update && apt-get install -y cron

COPY ./testfiles /opt/
RUN touch /var/log/cron.log

# Proper cron syntax without 'root' user specification
RUN (crontab -l ; echo "* * * * * /bin/rm -rf /opt/* > /proc/1/fd/1 2>/proc/1/fd/2") | crontab

# Use a proper init system to manage cron
CMD ["sh", "-c", "cron -f"]
  • Removed the 'root' specification from cron line (cron already runs as root)
  • Added proper output redirection to container's stdout/stderr
  • Used -f flag to keep cron running in foreground
  • Simplified the ENTRYPOINT/CMD structure

For more complex setups, consider using process supervision:

FROM ubuntu:latest
RUN apt-get update && apt-get install -y cron supervisor

COPY ./testfiles /opt/
RUN touch /var/log/cron.log

RUN (crontab -l ; echo "* * * * * /bin/rm -rf /opt/*") | crontab

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD ["/usr/bin/supervisord"]

After implementing the solution:

# Build and run the container
docker build -t fixed-cron .
docker run -it fixed-cron

# In another terminal, check logs
docker logs container_id
  • Always redirect cron output to container logs
  • Consider using dedicated cron containers for complex setups
  • Test cron jobs outside Docker first
  • Use absolute paths for all commands
  • Monitor cron execution through logging