Laravel 專案有排程要執行,但是 php-fpm container 裡沒有 crontab 指令,這是很常見的情況。
這時候不要急著把 cron 裝進 php-fpm。php-fpm 本來是處理網站 request 的,排程可以用別的方式做。
需求:
要定時執行:
php artisan forum:sync
例如每天 4 點和 15 點各執行一次。
方法一:由 Linux 主機 crontab 執行
可以直接在 host 的 crontab 裡呼叫 container 裡的 artisan:
docker exec -w /var/www/default php-fpm php artisan forum:sync
先手動測一次:
docker exec -w /var/www/default php-fpm php artisan forum:sync
如果可以正常執行,再加入 crontab:
crontab -e
每天 04:00 和 15:00 執行:
0 4,15 * * * /usr/bin/flock -n /tmp/forum-sync.lock /usr/bin/docker exec -w /var/www/default php-fpm php artisan forum:sync >> /var/log/forum-sync.log 2>&1
指令說明:
- 0 4,15 * * *
每天 4 點和 15 點執行。
- /usr/bin/flock -n /tmp/forum-sync.lock
避免上一輪還沒跑完,下一輪又啟動。
- /usr/bin/docker exec
從 host 執行 container 裡的指令。
- -w /var/www/default
指定 Laravel 專案所在目錄。
- >> /var/log/forum-sync.log 2>&1
把執行結果和錯誤訊息寫入 log。
方法二:建立 scheduler container
如果想比較 Docker 化,也可以另外建立一個 scheduler service:
laravel-scheduler:
image: "${PHP_VERSION}"
container_name: laravel-scheduler
working_dir: /var/www/default
volumes:
- ./wwwroot:/var/www
- ./session:/var/lib/php/session
environment:
TZ: ${TZ}
command: sh -c "while true; do php artisan schedule:run --verbose --no-interaction; sleep 60; done"
restart: unless-stopped
depends_on:
- mysql
啟動:
docker compose up -d laravel-scheduler
這種方式適合有使用 Laravel scheduler,也就是在 app/Console/Kernel.php 裡集中管理排程的專案。
常見錯誤:
如果出現:
Could not open input file: artisan
代表 -w /var/www/default 不是 Laravel 專案所在目錄,要改成實際路徑。
如果實際使用 PHP 8.3 container,就要把 container 名稱改成:
php83-fpm
結論:
php-fpm 裡沒有 crontab 不算問題。
簡單需求可以用 host crontab 呼叫:
docker exec ...
比較完整的 Laravel 排程,則可以用獨立 scheduler container。
不要把所有功能都塞進 php-fpm,之後比較好維護。

0 意見:
張貼留言