هر آموزش فارسی دیپلوی لاراول که باز میکنی، یک داستان تکراری است: فایل zip را در public_html آپلود کن، .env را ویرایش کن، پوشهٔ public را به روت منتقل کن و اگر ۵۰۰ گرفتی، پرمیشن storage را ۷۷۷ بگذار. این نسخهٔ سال ۱۳۹۷ است.
پروژهٔ امروز لاراول با صف، وبسوکت و Octane کار میکند و روی هاست اشتراکی نه پرمیشن درست دارد نه worker. این مقاله مسیر واقعیاش را میرود: از اتصال ریپو تا دامنه، با همان چهار چیزی که بعد از دیپلوی همه را زمین میزند.
در یک نگاه
- پیشنیاز
- نسخهٔ PHP در
composer.jsonمشخص باشد،.envدر ریپو نباشد، فایلهایpublic/buildساخته شده باشند - استقرار
- افزودن ریپو به حساب گیت، سپس انتخاب تایپ Laravel و نسخهٔ PHP (۷.۴ تا ۸.۵)
- اجرای migrations
- دستور post-deploy مثل
php artisan migrate --force - صف
- یک پروژهٔ جدا با تایپ Supervisor برای
queue:work - وبسوکت
- پروژهٔ جدا با تایپ Laravel Reverb، ولی قابل دسترس از مرورگر با
wss:// - دامنه و HTTPS
- سابدامین رایگان از لحظهٔ ساخت، دامنهٔ خودت بعداً
قبل از دیپلوی: چهار چیز را درست کن
اگر این چهار مورد مرتب باشد، دیپلوی لاراول روی هر پلتفرمی یک بار انجام میشود و دیگر دست نمیخورد:
- نسخهٔ PHP را اعلام کن: در
composer.jsonبنویس"php": "^8.2"تا پلتفرم حدس نزند. لکسویا از PHP 7.4 تا 8.5 را بهعنوان نسخهٔ پروژه پشتیبانی میکند. .envهرگز در ریپو نباشد: همهٔ کلیدها در متغیرهای محیطی پروژه مینشینند. اگر یکبار کلید دیتابیس کامیت شده باشد، عوضش کن؛ از تاریخ ریپو نمیشود پاکش کرد.- فایلهای بیلد فرانت را بساز: اگر Vite داری،
public/buildباید در ریپو باشد یا در مرحلهٔ بیلد ساخته شود. وگرنه صفحه بالا میآید ولی بیاستایل است. - دیتابیس از
localhostصدا نزن: در کانتینر، دیتابیس همان ماشین نیست. آدرس داخلی سرویس دیتابیس و پورتش را درDB_HOSTوDB_PORTبگذار.
پنج قدم تا نسخهٔ زنده
- حساب گیت را وصل کن. GitHub، GitLab یا Gitea؛ دسترسی فقط به همان ریپو داده میشود.
- پروژه را با تایپ Laravel بساز. نسخهٔ PHP را همینجا انتخاب میکنی (بعداً هم قابل تغییر است) و پورت کانتینر را میدهی.
- متغیرهای محیطی را بگذار.
APP_KEY،APP_ENV=production،APP_DEBUG=false، اطلاعات دیتابیس، و اگر Reverb داری کلیدهای آن. - پایپلاین را نگاه کن. بعد از ساخت، اولین بیلد خودکار اجرا میشود: نصب وابستگیها، بیلد، و استقرار بدون قطعی. لاگ هر مرحله را میشود زنده خواند.
- دامنه را بردار. سابدامین HTTPS آماده است؛ برای دامنهٔ خودت رکورد DNS را طبق پنل بگذار.
بعد از این، هر push خودش دیپلوی میشود. اگر نمیخواهی هر پوش مستقیم روی نسخهٔ زنده برود، CD را دستی کن یا پایپلاین خودکار را خاموش کن.
migrations را کجا اجرا کنیم؟
جواب درست: بعد از بیلد، قبل از سالم شدن نمونهٔ جدید. این کار با «دستور post-deploy» انجام میشود که بعد از هر استقرار موفق اجرا میشود. برای اکثر پروژهها همین کافی است:
php artisan migrate --force
php artisan config:cache
php artisan route:cacheدو نکته که با خون دل یاد میگیری: --force را فراموش نکن (در محیط غیرتعاملی بدون آن اجرا نمیشود)، و هرگز migrate:fresh را اینجا نگذار. migration باید idempotent باشد؛ اگر میگریت سنگینی داری که ممکن است timeout بخورد، اول با ترمینال تحت وب اجرایش کن و بعد در post-deploy بگذارش.
صف: چرا یک پروژهٔ جدا لازم است
queue:work یک پروسهٔ همیشهروشن است، نه یک درخواست HTTP. اگر در همان کانتینر وب اجرایش کنی، با هر دیپلوی و هر مقیاسدهی چند نسخه از آن بالا میآید یا کلاً میخوابد. راه درست:
- یک پروژه با تایپ Supervisor بساز و دایرکتوری کانفیگ را بده.
- دستورش همان چیزی است که روی سرور خودت مینوشتی:
php artisan queue:work --sleep=3 --tries=3 --max-time=3600 - بعد از هر دیپلوی،
php artisan queue:restartلازم است تا workerها کد جدید را بردارند؛ میتوانی همان را در post-deploy بگذاری. - worker را با ریپوی همان پروژه بالا بیاور، نه یک کپی جدا؛ وگرنه کد دو جای مختلف زندگی میکند.
وبسوکت با Laravel Reverb
Reverb یک سرور WebSocket است و مثل صف، پروسهٔ همیشهروشن میخواهد. لکسویا برایش تایپ اختصاصی دارد؛ پس دو پروژه داری: یکی اپ اصلی و یکی Reverb. سه چیزی که باید جور دربیاید:
- کلیدها یکسان باشند:
REVERB_APP_ID،REVERB_APP_KEYوREVERB_APP_SECRETدر هر دو پروژه با هم یکی باشند. - مرورگر به آدرس عمومی وصل شود: داخل شبکه آدرس داخلی کار میکند، ولی کلاینت از اینترنت میآید. یک دامنه یا سابدامین برای Reverb بگذار و در فرانت از
wss://استفاده کن. - پورت را درست نقشه بده: پورت WebSocket باید همان چیزی باشد که پلتفرم از بیرون میبیند، نه پورت داخلی کانتینر.
Octane: چه زمانی ارزش دارد، چه زمانی دردسر
Octane (در لکسویا روی FrankenPHP) اپ را در حافظه نگه میدارد و هر درخواست به boot جدید نیاز ندارد. برای APIهای پرترافیک تفاوت محسوسی میسازد. اما مدل ذهنیاش فرق دارد: کد بین درخواستها زنده میماند، پس هر حالت سراسری (استاتیک، سینگلتون با دادهٔ کاربر، کش دستی) میتواند از یک کاربر به کاربر دیگر سرریز کند.
اگر تازه لاراول را دیپلوی میکنی، اول ساده شروع کن. وقتی ترافیک واقعی داشتی و پروفایل کردی، مهاجرت به Octane فقط تغییر تایپ پروژه است نه بازنویسی.
خطاهای رایج بعد از اولین دیپلوی
| نشانه | علت معمول | راهحل |
|---|---|---|
| ۵۰۰ بعد از دیپلوی | APP_KEY خالی یا نبود پرمیشن نوشتن | php artisan key:generate و بررسی پرمیشن storage و bootstrap/cache |
| صفحه بالا میآید ولی بیاستایل است | نبود public/build | مرحلهٔ بیلد فرانت را اضافه کن یا خروجی Vite را کامیت کن |
could not find driver | افزونهٔ PDO دیتابیس در نسخهٔ PHP نیست | نسخهٔ پروژه را عوض کن یا درایور را در بیلد نصب کن |
| اتصال دیتابیس refused | DB_HOST=localhost | آدرس داخلی و پورت سرویس دیتابیس را بگذار |
| ایمیل یا job در صف میماند | دستور queue:workی وجود ندارد | پروژهٔ Supervisor را بالا بیاور و queue:restart بزن |
| وبسوکت وصل نمیشود | آدرس داخلی یا ws:// در صفحهٔ https | دامنهٔ عمومی Reverb و wss:// |
| فایل آپلودی بعد از دیپلوی گم میشود | نوشتن روی فایلسیستم کانتینر | دیسک ابری یا S3 را برای storage/app وصل کن |
بعد از دیپلوی چه چیزی را تست کن
فقط باز شدن صفحهٔ اول کافی نیست. حداقل این پنج چیز را یکبار دستی بزن: ثبتنام یا لاگین (نوشتن در دیتابیس)، یک صفحهٔ محافظتشده با session، یک job که واقعاً در صف اجرا شود، آپلود یک فایل، و یک اتصال وبسوکت. هر کدام از اینها یک لایهٔ متفاوت را امتحان میکند و همانجاست که مشکل پیدا میشود، نه در لندینگ.
اگر خطای بیلد یا پورت داری، راهنمای دیپلوی دستورها و دیباگ مرحلهبهمرحله را دارد. اگر هنوز بین سرور و پلتفرم مردد هستی، سرویس PaaS چیست و مقایسهٔ PaaS ایرانی را ببین.
جمعبندی
دیپلوی لاراول روی پلتفرم ابری، سه چیز را از تو میگیرد (سیستمعامل، وبسرور، SSL) و سه چیز را نگه میدارد که مال خود پروژه است: متغیرهای محیطی، migrations و workerها. اگر این سه را یکبار درست بچینی، از آن به بعد دیپلوی لاراول شده همان git push.
پروژهٔ لاراولیات را با git push بالا بیاور
تایپ اختصاصی Laravel، Octane و Reverb، دیتابیس مدیریتشده و دامنهٔ رایگان؛ پرداخت ساعتی بهازای منابع.
سؤالات متداول
دیپلوی لاراول روی پلتفرم ابری چقدر طول میکشد؟
برای پروژهای که composer.json و فایلهای بیلد فرانتش مرتب است، از اتصال گیت تا دامنهٔ HTTPS معمولاً چند دقیقه. بیشترِ وقت صرف اولین بیلد و حل متغیرهای محیطی میشود، نه خودِ استقرار.
Queue Worker را چطور اجرا کنم؟
یک پروژهٔ جدا با تایپ Supervisor بساز و دستور php artisan queue:work --sleep=3 --tries=3 --max-time=3600 را بگذار. worker را همیشهروشن میخواهی، پس نباید در کانتینر وب اجرا شود. بعد از هر دیپلوی queue:restart لازم است تا کد جدید برداشته شود.
migrations را کجا اجرا کنم؟
با دستور post-deploy که بعد از هر استقرار موفق اجرا میشود: php artisan migrate --force. در محیط غیرتعاملی بدون --force اجرا نمیشود. هرگز migrate:fresh را آنجا نگذار و migration سنگین را اول با ترمینال تحت وب تست کن.
برای وبسوکت باید Reverb بالا بیاورم یا Pusher؟
اگر نمیخواهی به سرویس خارجی وابسته باشی، Laravel Reverb گزینهٔ خودمیزبان است و لکسویا تایپ اختصاصی برایش دارد. فقط یادت باشد کلاینت مرورگر باید از طریق wss:// به دامنهٔ عمومی Reverb وصل شود، نه به آدرس داخلی کانتینر.
Octane را از اول فعال کنم؟
نه. اول نسخهٔ ساده را دیپلوی کن و درست کار کردن صف و دیتابیس را ببین. Octane (در لکسویا روی FrankenPHP) وقتی ارزش دارد که ترافیک واقعی و پروفایلشده داشته باشی؛ چون حالت بین درخواستها زنده میماند و کد سراسری میتواند سرریز کند.
چرا بعد از دیپلوی صفحه ۵۰۰ میدهد؟
سه علت رایج: APP_KEY خالی، پرمیشن نوشتن روی storage و bootstrap/cache، و خطای اتصال دیتابیس. اگر DB_HOST را localhost گذاشته باشی، دیتابیس در کانتینر دیگری است و وصل نمیشود؛ آدرس داخلی سرویس دیتابیس را بگذار.
فایلهای آپلودی کاربران را کجا ذخیره کنم؟
فایلسیستم کانتینر بعد از هر دیپلوی پاک میشود. برای storage/app یک دیسک ابری وصل کن یا از فضای S3 استفاده کن و درایور filesystem لاراول را روی s3 بگذار.
منابع
- مستندات دیپلوی Laravel در لکسویا؛ نسخههای PHP و مراحل ساخت پروژه.
- Laravel Octane (FrankenPHP) و Laravel Reverb؛ تایپهای اختصاصی پلتفرم.
- Supervisor؛ اجرای پردازشهای همیشهروشن مثل Queue Worker.
- مستندات رسمی دیپلوی لاراول.
- پلتفرم ابری لکسویا؛ کلاسترها، دیتابیس مدیریتشده و قیمت منابع.
مطالب مرتبط
- سرویس PaaS چیست؟ برای تعریف، مدل مسئولیت و پنج قدم اولیه.
- مقایسهٔ PaaS ایرانی اگر بین لیارا، پارسپک، چابکان و لکسویا مردد هستی.
- دیپلوی چیست؟ برای دیباگ خطاهای بیلد و پورت.
- Next.js چیست و چه سروری لازم دارد اگر پروژهات فرانتاند جدا دارد و باید کنار لاراول بالا بیاید.
- سرور MCP لکسویا برای اینکه همین دیپلوی را به عامل هوش مصنوعی بسپاری.