You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 23:35:18