cron on a docker container for laravel not working
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Mastering Cron in Docker: Solving the php artisan schedule:run Dilemma
As senior developers working with containerized applications, managing scheduled tasks like Laravel's scheduler within a Docker environment often presents unique challenges. You set up cron jobs, but when you move them into the isolated world of a container, execution can mysteriously fail. This post dives deep into why your cron setup is struggling to execute php artisan schedule:run inside your PHP-based container and provides a robust, Dockerfile-centric solution.
If you are working with Laravel, understanding how to manage background processes reliably is key to building scalable applications, much like the principles discussed at Laravel Company.
Diagnosing the Cron Failure in Containers
The symptoms you described—cron running simple commands but failing on complex ones like php artisan schedule:run, resulting in cryptic output like errors:insert > '/dev/null' 2>&1—point towards an environment mismatch rather than a fundamental flaw in cron itself.
When you run a command manually via SSH, your shell session inherits the full environment variables ($PATH, $HOME, etc.) and the correct context for finding PHP and Artisan. When the system cron daemon executes a job inside a container, it operates under a highly restricted, minimal execution context. Specifically:
- PATH Issues: Cron jobs often fail because they cannot locate the
phpexecutable or theartisanscript unless you explicitly define the full path within the crontab file, or if the cron environment is configured to use the application's specific entry point. - Permissions and Context: The user context under which the container runs cron might not have the necessary permissions or access to the application's dependencies needed for Laravel commands to execute successfully.
The strange ALERT: oops, unknown child (5094) exited with code 1 message is often a symptom of a process exiting unexpectedly due to environment failure, further confirming that the execution context was broken.
The Dockerfile Solution: Ensuring Robust Execution
To fix this reliably within your Docker setup, we need to stop relying on generic system cron scripts and instead ensure the command runs in an environment where it can correctly resolve application dependencies. We will modify your Dockerfile to use a custom script executed by cron, ensuring all necessary paths are respected.
Step 1: Create a Wrapper Script
Instead of trying to inject complex commands directly into /etc/cron.d/, we create a dedicated shell script that handles the execution, ensuring the correct working directory and environment are set up.
Create a file named run_schedule.sh in your project root:
#!/bin/sh
# Set the application root directory (adjust this path as necessary)
APP_ROOT="/var/www"
# Execute the schedule command using the full PHP binary path
# This ensures the cron environment can find the correct executable.
/usr/local/bin/php "$APP_ROOT/artisan" schedule:run >> /var/log/laravel-cron.log 2>&1
Step 2: Update the Dockerfile
We will update your Dockerfile to copy this script and ensure it is executable, making it the sole command cron executes for scheduling.
Here is the revised approach for your Dockerfile:
FROM php:7.0.4-fpm
# Install necessary packages and dependencies
RUN apt-get update \
&& apt-get install -y cron nano libmcrypt-dev \
mysql-client libmagickwand-dev --no-install-recommends \
&& pecl install imagick \
&& docker-php-ext-enable imagick \
&& docker-php-ext-install mcrypt pdo_mysql \
# Install the necessary PHP binary path if it's not standard (for robustness)
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Copy application files and the cron script
COPY . /var/www/
COPY run_schedule.sh /usr/local/bin/run_schedule.sh
# Make the script executable
RUN chmod +x /usr/local/bin/run_schedule.sh
# Setup Cron Job: Use the wrapper script for execution
# We use the standard crontab mechanism to schedule a daily run at 3 AM.
COPY crontab /etc/cron.d/laravel-cron
RUN chmod 0644 /etc/cron.d/laravel-cron
# Ensure cron is set up to execute our wrapper script
# Note: We are changing the entrypoint or ensuring the standard crontab points correctly.
# For Docker, relying on a simple crontab file is often cleaner if system cron is used.
RUN /usr/bin/crontab /etc/cron.d/laravel-cron
# Keep cron running (if needed, though usually services handle this)
CMD ["php-fpm"]
Step 3: Finalizing the Crontab Entry
Ensure your /etc/cron.d/laravel-cron file points to execute the wrapper script:
# m h dom mon dow command
0 3 * * * /usr/local/bin/run_schedule.sh
Conclusion: Consistency is Key in Containerized Scheduling
The key takeaway here is that scheduling tasks inside a container requires treating the execution environment as an isolated system, not just a standard shell session. By wrapping your complex command (php artisan schedule:run) into an executable script and forcing cron to execute this specific wrapper, you eliminate environmental ambiguity. This pattern—using dedicated scripts for background tasks within Docker—is a best practice for maintaining reliable, predictable application workflows, ensuring that your Laravel application operates smoothly, just as it should when deployed on platforms like Laravel Company.