Files
clinicpro/docs/deploy-liara.md
T

174 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# راهنمای دیپلوی ClinicPro روی لیارا (Docker)
این راهنما قدم‌به‌قدم نشان می‌دهد چطور بک‌اند Symfony را روی **لیارا** با پلتفرم **Docker** بالا بیاوری.
> چرا متفاوت با Coolify؟ لیارا **از docker-compose پشتیبانی نمی‌کند**. استک ۳-سرویسی compose (وب + ۲ worker) به یک **برنامهٔ داکر تکی** تبدیل شده که هر سه پروسه را با Supervisor اجرا می‌کند. MariaDB و Redis سرویس‌های مدیریت‌شدهٔ جدا روی شبکهٔ خصوصی‌اند.
---
## نمای کلی معماری
```
┌─────────────────────────── Liara private network ───────────────────────────┐
│ │
│ ┌────────────────────────────┐ ┌───────────────┐ ┌──────────────┐ │
│ │ clinicpro-api (Docker) │ │ MariaDB 11.8 │ │ Redis │ │
│ │ Supervisor: │◄────►│ (managed) │ │ (managed) │ │
│ │ • php-fpm + nginx :8080 │ └───────────────┘ └──────────────┘ │
│ │ • worker-async │ │
│ │ • worker-scheduler │ disks: jwt / uploads / var-uploads │
│ └─────────────┬──────────────┘ │
└─────────────────┼────────────────────────────────────────────────────────────┘
│ :8080 (تنها پورت HTTP بیرونی)
https://<your-domain>
```
فایل‌های کلیدی در ریپو:
- [`liara.json`](../liara.json) — پیکربندی دیپلوی (platform، port، دیسک‌ها، healthcheck)
- [`Dockerfile`](../Dockerfile) — image چندمرحله‌ای (بدون تغییر برای لیارا)
- [`docker/supervisord.conf`](../docker/supervisord.conf) — اجرای php-fpm + nginx + دو worker
- [`docker/entrypoint.sh`](../docker/entrypoint.sh) — wait-for-DB، تولید JWT، migration
- [`.env.liara.example`](../.env.liara.example) — مرجع متغیرهای محیطی
---
## پیش‌نیازها
```bash
npm i -g @liara/cli
liara login
```
مقادیری که از قبل آماده کن:
```bash
# APP_SECRET
php -r "echo bin2hex(random_bytes(32)).\"\n\";"
# JWT_PASSPHRASE
openssl rand -hex 32
# دامنه‌های فرانت (ALLOWED_FRONTEND_HOSTS + CORS_ALLOW_ORIGIN)
ddev exec php docker/gen-cors-env.php
```
---
## گام ۱ — ساخت دیتابیس و Redis
در [کنسول لیارا](https://console.liara.ir):
1. **MariaDB 11.8** بساز. (نسخه باید با `serverVersion=mariadb-11.8.0` در `DATABASE_URL` یکی باشد.)
2. **Redis** بساز.
3. روی هر دو **شبکهٔ خصوصی** را فعال کن.
4. **هاست خصوصی** و کاربر/رمز هرکدام را از صفحهٔ سرویس یادداشت کن (مثلاً `clinicpro-db`، `clinicpro-redis`).
---
## گام ۲ — ساخت برنامهٔ داکر
1. در کنسول یک **App** از نوع **Docker** بساز با شناسهٔ `clinicpro-api` (همان `app` در `liara.json`).
2. آن را به **همان شبکهٔ خصوصیِ** DB و Redis متصل کن.
---
## گام ۳ — ساخت دیسک‌های ماندگار
در صفحهٔ برنامه، بخش **Disks**، این سه دیسک را با **همین نام‌ها** بساز (مسیر mount از `liara.json` خوانده می‌شود):
| نام دیسک | mountTo | محتوا |
|---|---|---|
| `jwt` | `/app/config/jwt` | کلید JWT (نباید هر دیپلوی نو شود) |
| `uploads` | `/app/public/uploads` | فایل‌های عمومی آپلودی |
| `var-uploads` | `/app/var/uploads` | فایل‌های خصوصی آپلودی |
> ⚠️ بدون دیسک `jwt`، هر دیپلوی کلید جدید می‌سازد و **همهٔ توکن‌های صادرشده باطل** می‌شوند.
---
## گام ۴ — ست‌کردن متغیرهای محیطی
از روی [`.env.liara.example`](../.env.liara.example) مقادیر را در تب **Environment** یا با CLI ست کن:
```bash
liara env set APP_ENV=prod APP_DEBUG=0 --app clinicpro-api
liara env set APP_SECRET=<...> JWT_PASSPHRASE=<...> --app clinicpro-api
# هاست‌ها = هاست خصوصی سرویس‌های لیارا
liara env set DATABASE_URL="mysql://<user>:<pass>@<db-private-host>:3306/<db>?serverVersion=mariadb-11.8.0&charset=utf8mb4" --app clinicpro-api
liara env set REDIS_URL="redis://<redis-private-host>:6379" --app clinicpro-api
liara env set MESSENGER_TRANSPORT_DSN="redis://<redis-private-host>:6379/messages" --app clinicpro-api
liara env set APP_BASE_URL=https://<domain> DEFAULT_URI=https://<domain> --app clinicpro-api
liara env set TRUSTED_PROXIES="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1" --app clinicpro-api
liara env set ALLOWED_FRONTEND_HOSTS="<output>" CORS_ALLOW_ORIGIN="<output>" --app clinicpro-api
```
نکته‌ها:
- `RUN_INIT` را ست **نکن**`entrypoint.sh` پیش‌فرض `1` می‌گیرد و چون تک‌برنامه است، تولید JWT + migration یک‌بار اجرا می‌شود.
- کلیدهای SMS و درگاه پرداخت از **دیتابیس** خوانده می‌شوند، نه env.
---
## گام ۵ — دیپلوی
از ریشهٔ `clinicpro/`:
```bash
liara deploy
```
`liara.json` تنظیمات platform/port/disks/healthcheck را می‌دهد، پس فلگ اضافه لازم نیست. در اولین بالا آمدن:
1. `entrypoint.sh` تا ~۶۰ ثانیه صبر می‌کند تا DB جواب دهد.
2. کلید JWT می‌سازد (روی دیسک `jwt`).
3. کش prod را warmup می‌کند.
4. `doctrine:migrations:migrate` را اجرا می‌کند.
5. Supervisor، nginx/php-fpm و هر دو worker را بالا می‌آورد.
---
## گام ۶ — اتصال دامنه و تأیید
1. در بخش **Domains** برنامه، دامنهٔ API را وصل کن و TLS بگیر.
2. تست سلامت:
```bash
curl -i https://<domain>/health # باید 200 بدهد
```
3. لاگ‌ها:
```bash
liara logs --app clinicpro-api --follow
```
باید php-fpm، nginx، `worker-async` و `worker-scheduler` هر چهار بالا باشند.
4. ورود به پنل ادمین `/admin` و تست یک endpoint برای تأیید اتصال DB/Redis.
---
## دیپلوی‌های بعدی
```bash
git pull # یا تغییرات محلی
liara deploy
```
migrationهای جدید خودکار در `entrypoint.sh` اجرا می‌شوند. دیسک‌ها و env بین دیپلوی‌ها حفظ می‌شوند.
---
## رفع اشکال
| نشانه | علت محتمل | راه‌حل |
|---|---|---|
| `Database not reachable after 60s` در لاگ | شبکهٔ خصوصی وصل نیست یا `DATABASE_URL` غلط | DB و app روی یک شبکهٔ خصوصی باشند؛ هاست خصوصی و رمز را چک کن |
| توکن‌ها بعد از هر دیپلوی باطل | دیسک `jwt` mount نشده | دیسک `jwt` روی `/app/config/jwt` بساز |
| `/health` غیر-۲۰۰ | DB/Redis در دسترس نیست یا migration نخورده | لاگ entrypoint را ببین |
| خطای CORS از فرانت | `CORS_ALLOW_ORIGIN`/`ALLOWED_FRONTEND_HOSTS` قدیمی | `docker/gen-cors-env.php` را دوباره بزن و env را به‌روزرسانی کن |
| آپلودها بعد از دیپلوی گم می‌شوند | دیسک uploads mount نشده | دیسک‌های `uploads` و `var-uploads` را بساز |
---
## گزینهٔ جایگزین — worker مجزا
اگر خواستی workerها ایزوله باشند (به‌جای Supervisor تک‌کانتینر)، همین ریپو را به‌عنوان برنامهٔ داکر دومی با `liara.json` متفاوت دیپلوی کن که `command` را به `php bin/console messenger:consume ...` override کند، `RUN_INIT=0` بدهد و **بدون** پورت/دامنه باشد. گران‌تر (دو برنامهٔ داکر) ولی ایزوله‌تر. برای اکثر موارد گزینهٔ پیش‌فرض (Supervisor) کافی است.