steelforesight/liara-deploy.md

10 KiB
Raw Blame History

Liara Deployment Playbook (عمومی)

راهنمای عمومی دیپلوی روی Liara — جمع‌بندی مشکلات رایج و راه‌حل‌هاشون. برای هر پروژه‌ای قابل استفاده‌ست. جای <...>ها مقدار پروژه‌ی خودت رو بذار.

قرارداد نام‌گذاری در این سند: <app> = اسم اپ، <frontend-app> = اپ فرانت، <panel-app> = اپ بک‌اند/پنل، <db-internal-host> = هاست داخلی دیتابیس، <TOKEN> = API token لیارا، <port> = پورتی که اپ روش گوش می‌ده (Docker static: معمولاً 7860، Node: 3000).


۱) CLI — احراز هویت

مشکل: دستورها با Authentication failed رد می‌شن، حتی بعد از liara login (توکن بین شل‌ها/محیط‌ها share نمی‌شه).

راه‌حل: روی هر دستور --api-token بده:

liara deploy --app <app> --api-token "<TOKEN>"

توکن از داشبورد Liara → API.


۲) liara deploy روی prompt پورت هنگ می‌کنه

مشکل: دیپلوی روی Enter the port your app listens to: گیر می‌کنه و چیزی به Liara نمی‌رسه (مخصوصاً در حالت غیرتعاملی).

راه‌حل: پورت رو صریح بده — هم فلگ، هم liara.json:

liara deploy --app <app> --port <port> ...
{ "platform": "docker", "port": <port> }

اپ هم باید روی process.env.PORT گوش بده (Liara اون رو inject می‌کنه).


۳) Dockerfile cannot be empty

علت: .dockerignore خود Dockerfile رو exclude کرده.

راه‌حل: Dockerfile رو از .dockerignore بردار — Liara باید Dockerfile رو توی آرشیو ببینه.


۴) Docker Hub از ایران بلاکه (مهم‌ترین برای Docker)

مشکل: FROM <image> با Get "https://registry-1.docker.io/...": Client.Timeout exceeded تایم‌اوت می‌خوره.

راه‌حل: image پایه رو از میرور Liara بکش:

# ایمیج رسمی (node, nginx, postgres, python, ...):
FROM docker-mirror.liara.ir/library/<image>:<tag>
# ایمیج یوزر/سازمان:
FROM docker-mirror.liara.ir/<org>/<image>:<tag>

میرورهای دیگر Liara (در صورت نیاز داخل build):

نوع میرور
Docker Hub docker-mirror.liara.ir
Alpine (apk) https://linux-mirror.liara.ir/repository/alpine/
npm https://package-mirror.liara.ir/repository/npm/

npm ci/pip install معمولاً از ایران بدون میرور کار می‌کنن؛ فقط Docker Hub همیشه مشکل‌سازه. اگه داخل build apk add داری، میرور apk رو هم ست کن.


۵) لوکیشن build

نکته‌ی کلیدی: لوکیشن build ≠ لوکیشن میزبانی. اپ همیشه روی منطقه‌ی خودش سرو می‌شه؛ --build-location فقط می‌گه image کجا کامپایل شه.

  • build ایران + میرورهای بالا → سریع و بدون تحریم:
    liara deploy --app <app> --build-location iran ...
    
  • اگه از میرور استفاده نمی‌کنی، build ایران به Docker Hub نمی‌رسه (از مورد ۴ استفاده کن).

۶) متغیرهای build-time در فرانت (Vite / CRA / Next static)

مشکل: متغیر API URL رو به‌عنوان env روی اپ ست کردی ولی فرانت بهش وصل نشد.

علت: باندلرها متغیرهای VITE_* / REACT_APP_* / NEXT_PUBLIC_* رو موقع build داخل باندل می‌نویسن — env runtime روی کانتینر استاتیک بی‌اثره.

راه‌حل: توی Dockerfile قبل از build:

ARG VITE_API_URL=https://<panel-app>.liara.run
ENV VITE_API_URL=$VITE_API_URL
RUN npm run build

۷) اتصال اپ به دیتابیس (Private Network)

مشکل‌ها:

  • آدرس داخلی دیتابیس → getaddrinfo ENOTFOUND <db-internal-host>.
  • آدرس عمومی دیتابیس از داخل اپ Liara → ECONNREFUSED.

علت: اپ‌های Liara به endpoint عمومی DB وصل نمی‌شن؛ و هاست داخلی فقط وقتی resolve می‌شه که اپ و DB روی یک Private Network مشترک باشن.

راه‌حل:

  1. هم دیتابیس هم اپ رو به یک Private Network وصل کن.
  2. connection string کاملِ داخلی (نه فقط host:port):
    DATABASE_URL=postgresql://<user>:<pass>@<db-internal-host>:5432/<db>
    
  3. روی شبکه‌ی داخلی TLS لازم نیست (برعکس endpoint عمومی که TLS می‌خواد).

۸) اپ موقع بوت کرش می‌کنه چون env ست نیست

نشانه: کانتینر unhealthy / exit 255 و لاگ مثل FATAL: <X> is not set.

راه‌حل: env های حیاتی رو قبل از انتظارِ سالم‌بودن ست کن. تغییر env خودش ری‌استارت می‌کنه. ست با CLI (به‌جای داشبورد):

liara env:set "KEY=VALUE" "KEY2=VALUE2" --app <app> --force --api-token "<TOKEN>"

اگه کد بدون یه env حیاتی process.exit می‌کنه، تا ست نشه اصلاً بالا نمیاد.


۹) فایل‌سیستم Ephemeral

مشکل‌ها: دیتابیس فایلی (SQLite) و پوشه‌ی آپلود با هر ری‌دیپلوی پاک می‌شن؛ نوشتن/mkdir روی مسیرهای read-only کرش می‌کنه.

راه‌حل:

  • دیتای دائمی → دیتابیس مدیریت‌شده.
  • فایل/مدیا → Object Storage (مورد ۱۰).
  • اگه واقعاً دیسک لازمه → یه Disk بساز و mount کن؛ مسیر رو env-based کن.
  • هر نوشتن روی دیسک رو دفاعی بنویس که موقع بوت کرش نکنه:
    const dir = process.env.UPLOADS_DIR || path.join(__dirname, 'uploads');
    try { if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); } catch {}
    

۱۰) Object Storage (S3) برای مدیا

  • S3-compatible؛ endpoint مثل storage.iran.liara.site + bucket + access key + secret key.
  • در کد: SDK اس‌تری (@aws-sdk/client-s3forcePathStyle: true، endpoint = https://<endpoint>.
  • URL عمومی فایل: https://<bucket>.<endpoint>/<key>.
  • باکت رو public کن وگرنه فایل‌ها 403 می‌شن.

۱۱) پلتفرم اپ ثابته

نمی‌شه پلتفرم یه اپ رو عوض کرد (Node↔Docker↔Static). اگه اشتباه ساختی، پاک و با پلتفرم درست دوباره بساز (env و اتصال شبکه‌ی خصوصی رو هم از نو ست کن).


۱۲) CORS

مشکل: بک‌اند درخواست‌ها رو با Not allowed by CORS رد می‌کنه (حتی origin خودش).

راه‌حل: allow-list رو شامل دامنه‌ی خود اپ + دامنه‌ی فرانت کن:

ALLOWED_ORIGINS=https://<panel-app>.liara.run,https://<frontend-app>.liara.run

۱۳) Seed / یوزر ادمین

دیتابیس تازه خالیه → لاگین «رمز اشتباه». seed رو از Console اپ بزن. اگه اسکریپت seed یوزر موجود رو رد می‌کنه و رمز عوض نمی‌شه، از upsert استفاده کن. نکته‌ی مهم برای اسکریپت‌های seed: آدرس و رمز رو env-based کن تا هم لوکال هم روی Liara کار کنه:

const BASE = process.env.SEED_BASE || `http://localhost:${process.env.PORT || 3000}`;

روش بدون TLS-dependency: اسکریپت seed که فقط fetch می‌زنه رو می‌تونی از ماشین خودت با SEED_BASE=https://<panel-app>.liara.run اجرا کنی.


۱۴) همگام‌سازی lockfile

بعد از هر تغییر وابستگی‌ها، لوکال npm install بزن تا package-lock.json به‌روز شه، بعد دیپلوی — وگرنه npm ci روی Liara به‌خاطر mismatch خطا می‌ده. node_modules رو پوش نکن (.liaraignore / .dockerignore).


۱۵) لاگ و exit code گمراه‌کننده

  • liara deploy گاهی با exit code 2 تموم می‌شه ولی واقعاً موفق بوده (خطا فقط مرحله‌ی خوندن لاگ بعد از دیپلوی).
  • liara logs گاهی لاگ کش‌شده می‌ده.

راه‌حل: وضعیت واقعی رو از خروجی کامل دیپلوی (√ Release created / Deployment finished successfully) و یه درخواست HTTP واقعی به دامنه بگیر؛ به exit code تنها اعتماد نکن.


فایل‌های پایه‌ی هر اپ

liara.json (Docker):

{ "platform": "docker", "port": <port> }

liara.json (Node):

{ "platform": "node" }

.liaraignore:

node_modules
.env
*.db
uploads

چک‌لیست دیپلوی (ترتیب درست)

  1. دیتابیس بساز → Private Network روشن.
  2. اپ بک‌اند بساز → به همون Private Network وصلش کن.
  3. env های بک‌اند رو ست کن (DATABASE_URL داخلیِ کامل، سکرت‌ها، ALLOWED_ORIGINS، کلیدهای Object Storage، NODE_ENV=production).
  4. package-lock.json رو لوکال sync کن.
  5. (Docker) Dockerfile: میرور docker-mirror.liara.ir + ARG برای متغیرهای build-time. .dockerignore نباید Dockerfile رو حذف کنه.
  6. liara deploy --app <app> --port <port> --build-location iran --api-token "<TOKEN>".
  7. سلامت رو با درخواست HTTP به دامنه چک کن (نه فقط exit code).
  8. seed محتوا/ادمین (قبل از دیپلوی فرانت، تا سایت خالی نباشه).
  9. باکت Object Storage رو public کن.
  10. فرانت رو با متغیر build-time = دامنه‌ی بک‌اند دیپلوی کن؛ ALLOWED_ORIGINS بک‌اند رو شامل دامنه‌ی فرانت کن.