From 281521d56ead0b88d06a1235c65f62cb5d3874e8 Mon Sep 17 00:00:00 2001 From: Italo Date: Mon, 8 Jul 2024 02:23:46 -0400 Subject: [PATCH 1/4] Adds note for using cron --- .../4.laravel/2.laravel-task-scheduler.md | 90 ++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/docs/content/docs/4.laravel/2.laravel-task-scheduler.md b/docs/content/docs/4.laravel/2.laravel-task-scheduler.md index 62c45adf7..4d9bb4ced 100644 --- a/docs/content/docs/4.laravel/2.laravel-task-scheduler.md +++ b/docs/content/docs/4.laravel/2.laravel-task-scheduler.md @@ -16,6 +16,94 @@ Running a Laravel task scheduler with Docker can be a little different from the ## More detail We need to run the [schedule:work](https://laravel.com/docs/11.x/scheduling#running-the-scheduler-locally) command from Laravel. Although the docs say "Running the scheduler locally", this is what we want in production. It will run the scheduler in the foreground and execute it every minute. You can configure your Laravel app for the exact time that a command should run through a [scheduled task](https://laravel.com/docs/11.x/scheduling#scheduling-artisan-commands). +## Using cron +Laraver versions prior to 8.x don't have the `schedule:work` command, as [noted by this PR](https://github.com/laravel/framework/pull/34618). + +A non-invasive alternative is to incorporate the command manually in your application, which basically runs the scheduler each second on a loop. + +::codepanel +--- +label: A command that runs the Laravel Scheduler +--- +```php +namespace App\Console; + +use Illuminate\Console\Command; +use Illuminate\Support\Carbon; + +class ScheduleWorkCommand extends Command +{ + protected $name = 'schedule:work'; + protected $description = 'Start the schedule worker'; + + public function handle() + { + $this->info('Starting the Schedule worker.'); + + while (true) { + if (Carbon::now()->second === 0) { + $this->call('schedule:run'); + } + + sleep(1); + } + } +} +``` +:: + +If that is not an alternative, you will need to install `cron`, and add a cron entry to run the Laravel Scheduler each second. + +The best place to prepare cron would be in the production image, or before installing your application inside the container. Alpine images use Busybox, which includes `crond` out of the box, so there is no need to install it. + +::codepanel +--- +label: Installing cron and adding a Laravel Scheduler entry +--- +```dockerfile +# ... Prior build steps + +# Ensure we're root to install and prepare cron. +USER root + +# Set Laravel's Scheduler in the container default crontab file. +RUN printf "* * * * * www-data php /var/www/html/artisan schedule:run\n" >> /etc/crontab; + +# Install cron on Debian +RUN apt-get update && apt-get -y --no-install-recommends install cron && \ + rm -rf /var/lib/apit/lists/* + +# Copy our app files as www-data (33:33) +COPY --chown=www-data:www-data . /var/www/html + +# Ensure we are the unpriviledged www-data user +USER www-data + +# Install the application +RUN composer install +``` +:: + +In your Docker Compose file, you will need to call `cron` in the foreground. [On Debian](https://manpages.debian.org/bookworm/cron/cron.8.en.html), this is done with `/usr/sbin/cron -f -L 15`. On Alpine, [BusyBox's `crond`](https://busybox.net/downloads/BusyBox.html#crond) does the job as `/usr/sbin/crond -f -l 0`. + +::code-panel +--- +label: Calling the Laravel Scheduler through cron in Docker Compose File +--- +```yaml +services: + php: + image: my/laravel-app + environment: + PHP_FPM_POOL_NAME: "my-app_php" + + task: + image: my/laravel-app + command: ["/usr/sbin/cron", "-f", "-L", "15"] + environment: + PHP_FPM_POOL_NAME: "my-app_task" +``` +:: ## Examples Here is a simplified example of how you can achieve this with Docker Compose: @@ -88,4 +176,4 @@ class Kernel extends ConsoleKernel } } ``` -:: \ No newline at end of file +:: From cf3055c167b3b7666601f5c6d102946b47c6fc74 Mon Sep 17 00:00:00 2001 From: Italo Date: Fri, 4 Oct 2024 13:37:07 -0300 Subject: [PATCH 2/4] Minor fixes and clarifications --- .../4.laravel/2.laravel-task-scheduler.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/content/docs/4.laravel/2.laravel-task-scheduler.md b/docs/content/docs/4.laravel/2.laravel-task-scheduler.md index 4d9bb4ced..b006508af 100644 --- a/docs/content/docs/4.laravel/2.laravel-task-scheduler.md +++ b/docs/content/docs/4.laravel/2.laravel-task-scheduler.md @@ -17,7 +17,7 @@ Running a Laravel task scheduler with Docker can be a little different from the We need to run the [schedule:work](https://laravel.com/docs/11.x/scheduling#running-the-scheduler-locally) command from Laravel. Although the docs say "Running the scheduler locally", this is what we want in production. It will run the scheduler in the foreground and execute it every minute. You can configure your Laravel app for the exact time that a command should run through a [scheduled task](https://laravel.com/docs/11.x/scheduling#scheduling-artisan-commands). ## Using cron -Laraver versions prior to 8.x don't have the `schedule:work` command, as [noted by this PR](https://github.com/laravel/framework/pull/34618). +Laravel versions prior to 8.x don't have the `schedule:work` command, as [noted by this PR](https://github.com/laravel/framework/pull/34618). This may be also the case for non-Laravel applications that require external scheduling or do not ship with and scheduler process. A non-invasive alternative is to incorporate the command manually in your application, which basically runs the scheduler each second on a loop. @@ -52,9 +52,9 @@ class ScheduleWorkCommand extends Command ``` :: -If that is not an alternative, you will need to install `cron`, and add a cron entry to run the Laravel Scheduler each second. +If creating a command is not an alternative, you will need to install `cron`, and add a cron entry to run the Laravel Scheduler each second. -The best place to prepare cron would be in the production image, or before installing your application inside the container. Alpine images use Busybox, which includes `crond` out of the box, so there is no need to install it. +The best place to prepare cron would be in the production image, or before installing your application inside the container. Alpine images use Busybox, which includes `crond` out of the box, so there is no need to install it when using Alpine. ::codepanel --- @@ -66,17 +66,17 @@ label: Installing cron and adding a Laravel Scheduler entry # Ensure we're root to install and prepare cron. USER root -# Set Laravel's Scheduler in the container default crontab file. -RUN printf "* * * * * www-data php /var/www/html/artisan schedule:run\n" >> /etc/crontab; - # Install cron on Debian RUN apt-get update && apt-get -y --no-install-recommends install cron && \ rm -rf /var/lib/apit/lists/* +# Set Laravel's Scheduler in the container default crontab file running as the "www-data" user +RUN printf "* * * * * www-data php /var/www/html/artisan schedule:run\n" >> /etc/crontab + # Copy our app files as www-data (33:33) COPY --chown=www-data:www-data . /var/www/html -# Ensure we are the unpriviledged www-data user +# Ensure next instructions run as the unpriviledged "www-data" user USER www-data # Install the application @@ -84,7 +84,7 @@ RUN composer install ``` :: -In your Docker Compose file, you will need to call `cron` in the foreground. [On Debian](https://manpages.debian.org/bookworm/cron/cron.8.en.html), this is done with `/usr/sbin/cron -f -L 15`. On Alpine, [BusyBox's `crond`](https://busybox.net/downloads/BusyBox.html#crond) does the job as `/usr/sbin/crond -f -l 0`. +In your Docker Compose file, you will need to call `cron` in the foreground. [On Debian](https://manpages.debian.org/bookworm/cron/cron.8.en.html), this is done with `/usr/sbin/cron -f -L 15`. On Alpine, [BusyBox's `crond`](https://busybox.net/downloads/BusyBox.html#crond) does the job as `/usr/sbin/crond -f -l 0`. Both of these commands will run the process with verbose output. ::code-panel --- @@ -93,12 +93,12 @@ label: Calling the Laravel Scheduler through cron in Docker Compose File ```yaml services: php: - image: my/laravel-app + image: myself/laravel-app environment: PHP_FPM_POOL_NAME: "my-app_php" task: - image: my/laravel-app + image: myself/laravel-app command: ["/usr/sbin/cron", "-f", "-L", "15"] environment: PHP_FPM_POOL_NAME: "my-app_task" From 2a597bc0b288e024b4ba03515f09ac806d9996a3 Mon Sep 17 00:00:00 2001 From: Italo Date: Tue, 25 Feb 2025 13:39:54 -0300 Subject: [PATCH 3/4] Fix typo --- docs/content/docs/4.laravel/2.laravel-task-scheduler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/4.laravel/2.laravel-task-scheduler.md b/docs/content/docs/4.laravel/2.laravel-task-scheduler.md index 7ea7017c5..0e7ef6349 100644 --- a/docs/content/docs/4.laravel/2.laravel-task-scheduler.md +++ b/docs/content/docs/4.laravel/2.laravel-task-scheduler.md @@ -18,7 +18,7 @@ Running a Laravel task scheduler with Docker can be a little different from the We need to run the [schedule:work](https://laravel.com/docs/11.x/scheduling#running-the-scheduler-locally) command from Laravel. Although the docs say "Running the scheduler locally", this is what we want in production. It will run the scheduler in the foreground and execute it every minute. You can configure your Laravel app for the exact time that a command should run through a [scheduled task](https://laravel.com/docs/11.x/scheduling#scheduling-artisan-commands). ## Using cron -Laravel versions prior to 8.x don't have the `schedule:work` command, as [noted by this PR](https://github.com/laravel/framework/pull/34618). This may be also the case for non-Laravel applications that require external scheduling or do not ship with and scheduler process. +Laravel versions prior to 8.x don't have the `schedule:work` command, as [noted by this PR](https://github.com/laravel/framework/pull/34618). This may be also the case for non-Laravel applications that require external scheduling or do not ship with an scheduler process. A non-invasive alternative is to incorporate the command manually in your application, which basically runs the scheduler each second on a loop. From 0dd16097775b6a15b2d29c2bad75e01af4902599 Mon Sep 17 00:00:00 2001 From: Italo Date: Wed, 5 Mar 2025 17:53:15 -0300 Subject: [PATCH 4/4] Adds cron permissions fix --- docs/content/docs/4.laravel/2.laravel-task-scheduler.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/content/docs/4.laravel/2.laravel-task-scheduler.md b/docs/content/docs/4.laravel/2.laravel-task-scheduler.md index 0e7ef6349..a1cc9fff6 100644 --- a/docs/content/docs/4.laravel/2.laravel-task-scheduler.md +++ b/docs/content/docs/4.laravel/2.laravel-task-scheduler.md @@ -77,6 +77,10 @@ RUN printf "* * * * * www-data php /var/www/html/artisan schedule:run\n" >> /etc # Copy our app files as www-data (33:33) COPY --chown=www-data:www-data . /var/www/html +# Ensure the Cron service (and its PID) runs in the container +RUN chmod gu+s /usr/sbin/cron && \ + chmod gu+rw /var/run + # Ensure next instructions run as the unpriviledged "www-data" user USER www-data