如何在Docker启动Laravel容器时仅执行一次指定命令(无需bash脚本)
实现Laravel容器启动时单次执行自定义逻辑
方法步骤:
1. 创建自定义Artisan命令
首先生成专属命令来封装启动逻辑:
php artisan make:command LogServiceStarted
打开生成的app/Console/Commands/LogServiceStarted.php,替换内容如下:
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Log; class LogServiceStarted extends Command { protected $signature = 'service:log-started'; protected $description = '记录服务启动日志,每个容器启动周期仅执行一次'; public function handle() { // 用缓存锁确保同一启动周期内只执行一次,有效期设为1小时(覆盖常规启动周期) $lock = Cache::lock('service_started_log', 3600); if ($lock->get()) { Log::info('Service is running'); $this->info('服务启动日志已记录'); } else { $this->info('本次启动周期内已执行过日志记录'); } } }
2. 调整容器启动脚本
修改你的entrypoint.sh,在启动主服务(如php-fpm、nginx)之前调用这个Artisan命令:
#!/bin/sh # 执行自定义启动逻辑命令 php artisan service:log-started # 启动主服务 exec php-fpm
备选方案:使用文件锁(无需依赖缓存)
如果不想依赖缓存,也可以通过本地文件锁实现,同时处理异常退出的锁文件清理:
public function handle() { $lockFile = storage_path('app/service_started.lock'); if (!file_exists($lockFile)) { file_put_contents($lockFile, time()); Log::info('Service is running'); $this->info('服务启动日志已记录'); // 注册 shutdown 钩子,容器退出时自动删除锁文件 register_shutdown_function(function () use ($lockFile) { if (file_exists($lockFile)) { unlink($lockFile); } }); } else { $this->info('本次启动周期内已执行过日志记录'); } }
说明
- 缓存锁方案更可靠:容器重启后,内部默认文件缓存会清空,每次启动都会重新执行一次逻辑;若使用Redis等外部缓存,需确保缓存键的生命周期匹配容器启动周期。
- 文件锁方案需注意:若容器异常崩溃,锁文件可能残留,导致下次启动不执行逻辑,适合容器能正常退出的场景。
内容的提问来源于stack exchange,提问作者Lucas Fernandes
相关产品推荐
相关产品推荐

