feat: 新增 Docker 部署支持、Swoole/Octane 集成及相关优化

- 添加 Dockerfile 与多套 docker-compose 配置(开发/生产环境)
- 集成 Laravel Octane (Swoole) 提升性能
- 新增健康检查、监控脚本及部署文档
- 新增 Docker 镜像离线导入包(MySQL/Redis/Meilisearch)
- 优化文档转换、预览服务及队列任务
- 添加 CreateAdminUser 命令与路由健康检查接口
- 新增 Swoole 队列兼容性测试套件

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 15:51:19 +08:00
parent acf549c43c
commit 3c206e9e06
90 changed files with 12731 additions and 1255 deletions

View File

@@ -2,11 +2,88 @@
use App\Http\Controllers\DocumentController;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
Route::get('/', function () {
return view('welcome');
});
// 健康检查路由用于Docker健康检查
Route::get('/health', function () {
$services = [];
$allHealthy = true;
try {
// 检查数据库连接
DB::connection()->getPdo();
$services['database'] = 'connected';
} catch (Exception $e) {
$services['database'] = 'disconnected';
$allHealthy = false;
}
try {
// 检查Redis连接
if (config('cache.default') === 'redis') {
Cache::store('redis')->put('health_check', 'ok', 10);
Cache::store('redis')->forget('health_check');
$services['redis'] = 'connected';
} else {
$services['redis'] = 'not_configured';
}
} catch (Exception $e) {
$services['redis'] = 'disconnected';
$allHealthy = false;
}
try {
// 检查Meilisearch连接
if (config('scout.driver') === 'meilisearch') {
$client = new \GuzzleHttp\Client();
$response = $client->get(config('scout.meilisearch.host') . '/health', [
'timeout' => 5,
'headers' => [
'Authorization' => 'Bearer ' . config('scout.meilisearch.key')
]
]);
if ($response->getStatusCode() === 200) {
$services['meilisearch'] = 'connected';
} else {
$services['meilisearch'] = 'unhealthy';
$allHealthy = false;
}
} else {
$services['meilisearch'] = 'not_configured';
}
} catch (Exception $e) {
$services['meilisearch'] = 'disconnected';
$allHealthy = false;
}
// 检查存储目录是否可写
try {
$testFile = storage_path('logs/health_check_test.tmp');
file_put_contents($testFile, 'test');
unlink($testFile);
$services['storage'] = 'writable';
} catch (Exception $e) {
$services['storage'] = 'not_writable';
$allHealthy = false;
}
$status = $allHealthy ? 'ok' : 'degraded';
$httpCode = $allHealthy ? 200 : 503;
return response()->json([
'status' => $status,
'timestamp' => now()->toISOString(),
'services' => $services,
'version' => config('app.version', '1.0.0')
], $httpCode);
})->name('health.check');
// 文档预览和下载路由(需要认证)
Route::middleware(['auth'])->group(function () {
Route::get('/documents/{document}/preview', [DocumentController::class, 'preview'])