CONTAINER APPS · راهنمای CDNCTL
انتقال یک پروژه داکر چندسرویسی، سرتاسر با cdnctl
این راهنما نحوه بردن یک پروژه چندسرویسی بهسبک docker-compose (سرویسهای وب/API، worker های پسزمینه، یک پایگاهداده، یک کش و یک صف پیام) و اجرای آن روی پلتفرم کانتینر مدیریتشده CDN.com.tr را — کاملاً از خط فرمان cdnctl — گامبهگام شرح میدهد. مقادیر جایگیرنده (<account-uuid>، نامهای ایمیج، پورتها) را با مقادیر خودتان جایگزین کنید.
اگر از قبل یک docker-compose.yml دارید، میتوانید مراحل دستی ساخت-و-اتصال زیر را رد کنید: پلتفرم فایل compose شما را تجزیه میکند و یک برنامه آمادهتأیید پیشنهاد میدهد. به راهنمای وارد کردن Docker Compose یا مرجع compose در cdnctl مراجعه کنید. مراحل سرتاسر اینجا برای تنظیم دقیق یا انتقال هرچیزی که وارد کردن compose پوشش نمیدهد همچنان راه استاندارد باقی میمانند.
۱ · مفاهیم
- حساب = پروژه. یک حساب میتواند چندین container app داشته باشد؛ بسته شما تعداد اپهایی که میتوانید اجرا کنید را تعیین میکند.
- اپ = یک ایمیج کانتینر (یک سرویس). هر اپ یک پورت، یک بررسی سلامت، منابع، متغیرهای env و secret ها دارد، و میتواند تا N رپلیکا مقیاسدهی شود.
- افزونههای مدیریتشده بکاندهای دارای وضعیتی هستند —
postgres(PostgreSQL/TimescaleDB)،mysql،redisوnats(JetStream) — که به یک اپ متصل میکنید. هر افزونه برای اپی که آن را روی آن فعال میکنید فراهم میشود و یک hostname پایدار درون-خوشهای ارائه میدهد. جزئیات اتصال آن — host، پورت، کاربر، پایگاهداده و رمز عبور تولیدشده — بهصورت متغیرهای env و secret مستقیماً به آن اپ تزریق میشوند (مثلاًDATABASE_URL،REDIS_URL،NATS_URL)، آماده استفاده. رمز عبور برای شما تولید میشود و هرگز دوباره نمایش داده نمیشود، پس رشتههای اتصال را برای اپ مالک بهصورت دستی نمیسازید. - شبکه خصوصی و کشف سرویس. اپهای داخل حساب شما یک شبکه خصوصی مشترک دارند. هر اپ از اپهای دیگر شما با نام اپ خودش قابل دسترسی است — دقیقاً مانند یک نام سرویس docker-compose — در
http://<app-name>:<port>(ما یک نام مستعار DNS داخلی برابر با نام اپ شما منتشر میکنیم). پس اگر فایل compose شما باhttp://hot-data-store:8082صحبت میکند، آن اپ راhot-data-storeبا پورت8082نامگذاری کنید و بهسادگی کار میکند. اپها میتوانند به اینترنت دسترسی داشته باشند اما نه به سرویسهای خصوصی سایر مشتریان. - host های افزونه به شما بازگردانده میشوند. وقتی یک افزونه را فعال میکنید، host پایدار درون-خوشهای آن توسط
cdnctl container addons list(فیلدhost) گزارش میشود. همین است<db-host>/<redis-host>/<nats-host>استفادهشده در رشتههای اتصال زیر — آن را حدس نمیزنید. - انتشار عمومی. هر اپ میتواند روی یک سابدامین CDN.com.tr یا دامنه خودتان منتشر شود. هر سرویس منتشرشده hostname مخصوص به خودش را میگیرد.
۲ · cdnctl را پیکربندی کنید
یکبار با توکن API پنل خود احراز هویت کنید (یا با login با اعتبارنامههای خود وارد شوید):
cdnctl configure --endpoint https://cdn.com.tr --token <your-api-token>
# verify
cdnctl accounts list
cdnctl container apps list --account <account-uuid>
۳ · ایمیجها را بسازید و منتشر کنید، یک اعتبارنامه pull ثبت کنید
هر سرویس را برای linux/amd64 بسازید و به یک رجیستری که پلتفرم بتواند pull کند push کنید. اگر مخزنها خصوصیاند، یک اعتبارنامه pull روی حساب ثبت کنید:
# build & push (one image per service)
docker buildx build --platform linux/amd64 -t your-registry/app-web:1.0.0 --push .
docker buildx build --platform linux/amd64 -t your-registry/app-worker:1.0.0 --push .
# register pull credentials (token is stored encrypted, never returned)
cdnctl container registry-credentials create --account <account-uuid> \
--name registry --registry-url https://index.docker.io/v1/ \
--username <user> --password <token>
cdnctl container registry-credentials list --account <account-uuid>
هرگز secret ها را داخل ایمیجها نگذارید. برای حذف .env، خروجیهای build و دادههای VCS از یک .dockerignore استفاده کنید.
۴ · افزونههای مدیریتشده را فراهم کنید (DB، کش، صف پیام)
هر افزونه به یک اپ متصل میشود، پس ابتدا آن اپ را میسازید (مرحله ۵) و سپس افزونهها را روی آن فعال میکنید. افزونه برای آن اپ فراهم میشود و اتصالش بهطور خودکار به آن تزریق میشود — URL را مونتاژ یا رمز عبور را کپی نمیکنید:
# enable the backends your owner app needs (app created in step 5):
cdnctl container addons enable-postgres --account <account-uuid> --app <app-uuid> --storage-mb 10240
cdnctl container addons enable-redis --account <account-uuid> --app <app-uuid>
cdnctl container addons enable-nats --account <account-uuid> --app <app-uuid> --storage-mb 5120
cdnctl container addons list --account <account-uuid> --app <app-uuid>
از این پس محیط آن اپ از قبل مقادیر آماده استفاده دارد — به آنها ارجاع میدهید، آنها را نمیسازید:
# auto-injected into the app the addon is enabled on:
DATABASE_HOST, DATABASE_PORT, DATABASE_NAME, DATABASE_USER # env
DATABASE_PASSWORD, DATABASE_URL # secrets (full postgres:// URL)
REDIS_URL # redis://<redis-host>:6379/0
NATS_URL # nats://<nats-host>:4222
cdnctl container addons list، host پایدار، پورت، کاربر و نام پایگاهداده هر افزونه (مثلاً host: ca-…-postgres) را برای مرجع گزارش میدهد — رمز عبور تولیدشده هرگز برگردانده نمیشود. پس نیازی نیست DATABASE_URL را برای اپ مالک بهصورت دستی بنویسید؛ از قبل یک secret روی آن است.
اشتراکگذاری یک بکاند بین اپها. بکاندهای بدون رمز عبور — NATS، و Redis با پیکربندی اینجا — میتوانند از اپهای دیگر شما نیز دسترسیپذیر باشند: host را از addons list بگیرید و NATS_URL/REDIS_URL را روی هر مصرفکننده env تنظیم کنید (مرحله ۵). یک پایگاهداده SQL دارای رمز عبور متفاوت است: چون رمز عبور فقط به اپ مالک افزونه تزریق میشود (و هرگز نمایش داده نمیشود)، سعی نکنید آن را از یک اپ دوم دوباره استفاده کنید. بهجای آن، یا بگذارید یک اپ مالک پایگاهداده باشد و بقیه از طریق API شما به آن دسترسی داشته باشند، یا ایمیج پایگاهداده خودتان را با رمز عبوری که خودتان تعیین میکنید اجرا کنید. host های اپ-به-اپ فقط نامهای اپ شما هستند (نام مستعار بهسبک docker-compose از مرحله ۱)، پس URL هایی مانند http://hot-data-store:8082 بدون آپلود هیچ docker-compose.yml resolve میشوند.
۵ · هر سرویس را بسازید و متصل کنید
یک اپ بهازای هر سرویس بسازید. ترتیب این است: اپ را بساز → افزونههای آن را فعال کن (مرحله ۴) → مستقر کن (مرحله ۶). فعال کردن یک افزونه، اپ را با اتصال تزریقشده دوباره مستقر میکند، پس ابتدا اپ مالک افزونه را اینجا بسازید، سپس دستورهای مرحله-۴ را روی آن اجرا کنید. بررسی سلامت درست را بر اساس نوع سرویس انتخاب کنید:
--healthcheck-type http(پیشفرض) برای سرویسهای HTTP —--healthcheck /your/pathرا تنظیم کنید.--healthcheck-type tcpبرای سرویسهای TCP بدون یک اندپوینت HTTP.--healthcheck-type noneبرای worker های پسزمینهای که listen نمیکنند.
# app-web OWNS the postgres/redis/nats addons you enable in step 4, so DATABASE_URL,
# REDIS_URL and NATS_URL are injected for you — you only add your own secrets here:
cdnctl container apps create --account <account-uuid> \
--name app-web --image your-registry/app-web --tag 1.0.0 \
--port 8080 --healthcheck-type http --healthcheck /health \
--metrics-port 9090 --metrics-path /metrics \
--registry-credential <cred-uuid> \
--secrets-json '{"API_KEY":"<secret>"}'
# a background worker that shares the message bus. It does NOT own the addons, so point it
# at the passwordless NATS host from `addons list` (there is no DB password to copy):
cdnctl container apps create --account <account-uuid> \
--name app-worker --image your-registry/app-worker --tag 1.0.0 \
--healthcheck-type none --registry-credential <cred-uuid> \
--env-json '{"NATS_URL":"nats://<nats-host>:4222"}' \
--secrets-json '{"API_KEY":"<secret>"}'
secret های ارسالشده با --secrets-json بهصورت Kubernetes secret رمزنگاریشده ذخیره میشوند و هرگز در پیکربندی ساده یا لاگها قرار نمیگیرند. env/secret ها را بعداً با cdnctl container apps update --account <account-uuid> --app <app-uuid> --env-json ... --secrets-json ... بهروزرسانی کنید.
۶ · استقرار دهید، وضعیت و لاگها را بررسی کنید
هر اپ را مستقر کنید (اگر اپهای شما هنگام بوت مایگریشن اجرا میکنند، ابتدا سرویسی که طرحواره پایگاهداده را مقداردهی اولیه میکند مستقر کنید):
cdnctl container apps deploy --account <account-uuid> --app <app-uuid>
cdnctl container apps status --account <account-uuid> --app <app-uuid>
cdnctl container apps wait --account <account-uuid> --app <app-uuid> --status running --timeout 300
cdnctl container apps logs --account <account-uuid> --app <app-uuid> --tail 100
cdnctl container apps diagnose --account <account-uuid> --app <app-uuid>
۷ · سرویسها را بهصورت عمومی منتشر کنید
به یک سرویس سابدامین CDN.com.tr مخصوص خودش بدهید (HTTPS برای شما مدیریت میشود):
cdnctl container apps expose --account <account-uuid> --app <app-uuid>
# returns the app's public_subdomain, e.g. https://<uid>.cdn.com.tr
هر اپ یک سابدامین ثابت میگیرد؛ هر تعداد سرویسی که لازم دارید منتشر کنید — یک حساب، چندین hostname عمومی. برای استفاده از دامنه خودتان بهجای آن، آن را بهعنوان یک delivery point اضافه کنید و به سمت اپ اشاره دهید (دامنه شما → CDN → سرویس).
فقط سرویسهایی را منتشر کنید که باید عمومی باشند. worker های پسزمینه و پایگاهدادهها خصوصی میمانند. به هر سرویس HTTP که منتشر میکنید احراز هویت اضافه کنید.
۸ · قابلیت رصد (یک نمای واحد)
پشته پایش خود را بهعنوان اپهای معمولی اجرا کنید: یک جمعآور متریک که سرویسهای شما را scrape میکند، بههمراه یک داشبورد که بهصورت عمومی منتشر میکنید. جمعآور را خصوصی نگه دارید و فقط داشبورد را منتشر کنید:
# collector (internal): build an image with your scrape config baked in
cdnctl container apps create --account <account-uuid> --name metrics \
--image your-registry/metrics --tag 1.0.0 --port 9090 --healthcheck-type http --healthcheck /-/healthy \
--registry-credential <cred-uuid>
cdnctl container apps deploy --account <account-uuid> --app <metrics-app-uuid>
# dashboard: wire it to the collector via env, then expose it
cdnctl container apps create --account <account-uuid> --name dashboard \
--image your-registry/dashboard --tag 1.0.0 --port 3000 --healthcheck-type http --healthcheck /api/health \
--registry-credential <cred-uuid> \
--env-json '{"METRICS_URL":"http://<metrics-host>:80"}' --secrets-json '{"ADMIN_PASSWORD":"<secret>"}'
cdnctl container apps deploy --account <account-uuid> --app <dashboard-app-uuid>
cdnctl container apps expose --account <account-uuid> --app <dashboard-app-uuid>
۹ · چرخه عمر و بازگردانی
cdnctl container apps scale --account <account-uuid> --app <app-uuid> --replicas 0 # stop
cdnctl container apps restart --account <account-uuid> --app <app-uuid>
cdnctl container apps delete --account <account-uuid> --app <app-uuid> # removes app + its subdomain
cdnctl container addons disable-postgres --account <account-uuid> --app <app-uuid> # keeps data
cdnctl container addons disable-postgres --account <account-uuid> --app <app-uuid> --delete-data --confirmation <app-name>
غیرفعال کردن یک افزونه داده بهطور پیشفرض دیسک آن را نگه میدارد؛ حذف داده به یک تأیید صریح نیاز دارد. حذف یک اپ سابدامین عمومی آن را نیز حذف میکند.