🚀 Deploy Workflow A-Z
Hướng dẫn từ register → deploy app thật → bind domain → troubleshoot. 5 phút đọc.
1.Hiểu workflow trước khi click
Zeni Cloud deploy mỗi project = 1 service Cloud Run độc lập. Để deploy app của bạn, cần 1 image Docker. Có 3 cách lấy image:
① Upload ZIP source
Bạn upload file zip code → Zeni tự build Docker image. Phù hợp Next.js/Vite/FastAPI/Express với Dockerfile chuẩn.
POST /api/v1/upload/source
② Build Farm (native)
Build Tauri/Rust/Electron/Go/Flutter/.NET trên cloud. Khách KHÔNG cần cài rustc/MSVC/Xcode local.
POST /api/v1/build-farm/jobs
③ Image có sẵn Docker Hub
Dùng image public hoặc private đã build sẵn, push lên Docker Hub / Artifact Registry.
docker.io/yourname/app:v1
2.5 bước deploy
-
Đăng ký + Login
Vào zenicloud.io → click "Đăng ký" → nhập email + password (mạnh ≥8 ký tự). Sau khi register, hệ thống tự tạo personal workspace cho bạn (tên = email slug).
⚠️ Token JWT hết hạn sau 1 giờ. Nếu thấy "Phiên đăng nhập hết hạn" → login lại (Zeni tự redirect). -
Click "+ Project mới"
Trên dashboard, button góc trên-phải. Mở wizard 4 bước:
Bước Chọn gì 1 Loại: Web App/API/Worker/AI Agent2 Tên project (3-48 ký tự, lowercase + dash) + region (mặc định asia-southeast1Singapore — nhanh nhất cho VN)3 Runtime + Size: Node 20 / Python 3.12 / Go / Static; Size XS-Large + GPU 4 Confirm — đọc kỹ "💡 Lưu ý quan trọng" về image mặc định -
Chọn cách đặt image (CHÍNH YẾU)
Khi confirm Step 4, image mặc định là
us-docker.pkg.dev/cloudrun/container/hello— placeholder Google. Nếu bạn click Tạo & Deploy ngay, project sẽ chạy trang "Hello World" của Google, KHÔNG phải code của bạn.✅ Để deploy CODE THẬT, sau khi project tạo, làm 1 trong 3 cách:① Upload ZIP② Build Farm③ Docker HubPhù hợp: Next.js, React Vite, Vue, FastAPI, Express, Static HTML.
# Zip thư mục code (loại trừ node_modules, .git, .env) zip -r my-app.zip . -x "node_modules/*" ".git/*" ".env*" # Upload qua API curl -X POST 'https://zenicloud.io/api/v1/upload/source?ws=YOUR_WS&framework=auto' \ -H "Authorization: Bearer $ZENI_TOKEN" \ -F "file=@my-app.zip" \ -F "project_name=my-app" # Zeni tự detect framework + generate Dockerfile + build + deploy # Trả về upload_id, poll status: curl 'https://zenicloud.io/api/v1/upload/source/{upload_id}?ws=YOUR_WS' \ -H "Authorization: Bearer $ZENI_TOKEN"Hoặc dùng CLI
npm install -g @zenicloud/clirồizeni deploy.Phù hợp: Tauri (.exe / .dmg / .AppImage), Rust binary, Electron app, Go static, Flutter mobile, .NET 8.
curl -X POST 'https://zenicloud.io/api/v1/build-farm/jobs?ws=YOUR_WS' \ -H "Authorization: Bearer $ZENI_TOKEN" \ -d '{ "toolchain": "tauri-latest", "source_type": "github", "source_ref": "github://thienmocduc/my-tauri-app@main", "target_platforms": ["windows-x64", "linux-x64"] }' # Returns job_id. Poll until status="success": curl 'https://zenicloud.io/api/v1/build-farm/jobs/{job_id}?ws=YOUR_WS' \ -H "Authorization: Bearer $ZENI_TOKEN" # Artifact URL trả về sau build success — download .exe / .dmg / .AppImageHỗ trợ 6 toolchain:
tauri-latest,rust-stable,electron-builder,go-modules,flutter-stable,dotnet-8.Phù hợp: Bạn đã có Docker image build sẵn, push lên Docker Hub / Artifact Registry.
# Build + push lên Docker Hub docker build -t yourname/my-app:v1 . docker push yourname/my-app:v1 # Update project image qua API curl -X PATCH 'https://zenicloud.io/api/v1/projects/{project_id}/image?ws=YOUR_WS' \ -H "Authorization: Bearer $ZENI_TOKEN" \ -d '{"image": "docker.io/yourname/my-app:v1"}' # Hoặc tạo project mới với image này từ đầu (Step 4 wizard có field "Image")Tip: Public Docker Hub OK ngay. Private cần wire credentials qua/identity/secrets. -
Deploy + Poll status
Sau khi click "Tạo & Deploy" hoặc gọi API, status chuyển:
deploying→running(~30-60s). Cloud Run service tạo ra với URL dạnghttps://zeni-{ws}-{project}-xxx.a.run.app.curl 'https://zenicloud.io/api/v1/projects/{project_id}?ws=YOUR_WS' \ -H "Authorization: Bearer $ZENI_TOKEN" # Response: { "id": "...", "status": "running", "domain": "https://zeni-myws-myapp-lijavjpb2a-as.a.run.app", "version": "rev-myws-myapp-00001-abc" } -
Bind custom domain
Nếu bạn muốn URL riêng (vd:
app.example.com):curl -X POST 'https://zenicloud.io/api/v1/projects/{project_id}/domain?ws=YOUR_WS' \ -H "Authorization: Bearer $ZENI_TOKEN" \ -d '{"domain": "app.example.com"}' # Response trả CNAME records cần add vào DNS: { "status": "pending_dns", "dns_records": [ {"type": "CNAME", "name": "app", "value": "ghs.googlehosted.com"} ] }Add CNAME vào Namecheap/Cloudflare DNS → đợi 5-15 phút → SSL auto-issue. Domain LIVE.
3.Troubleshoot lỗi thường gặp
❌ "missing bearer token" (HTTP 401)
Nguyên nhân: Token JWT trong localStorage browser hết hạn (TTL 1h) hoặc bị clear.
Fix: Logout → Login lại. Sau v121, frontend tự redirect login khi detect token expire.
❌ "Image 'X' không tồn tại trong registry" (HTTP 422)
Nguyên nhân: Bạn submit image ref (vd: gcr.io/project/app:v1) nhưng chưa build/push image lên registry.
Fix: Build image trước (1 trong 3 cách trên), HOẶC dùng Docker Hub public (docker.io/library/nginx:alpine).
❌ "Container failed to start on PORT=3000"
Nguyên nhân: App của bạn không listen đúng port. Cloud Run truyền env PORT, app phải listen port đó (default 8080).
Fix: Sửa code app: app.listen(process.env.PORT || 8080). Hoặc khi tạo project, chỉnh field port đúng với app của bạn.
❌ "Workspace access denied" (HTTP 403)
Nguyên nhân: Bạn login OK nhưng không có quyền vào workspace đó.
Fix: Liên hệ Owner workspace để invite bạn qua tab Members. Hoặc tạo workspace riêng.
❌ Build Farm fail "image not found"
Nguyên nhân: Toolchain image gcr.io/zeni-cloud-core/build-farm/tauri:2 chưa build (Phase 2 pending).
Workaround: Tạm dùng GitHub Actions hoặc local build → push image lên Docker Hub → deploy ZeniCloud qua cách ③.
📚 Tiếp theo nên đọc
- Full Features — list 6 lớp hạ tầng + 11 services Sprint 1-2
- Quickstart 5 phút — Hello World từ đầu
- Custom Domain — bind domain chi tiết
- AI Engine — call Claude/Gemini/GPT qua /ai/complete
- Cron Jobs — schedule tasks
- PWA Templates — install-able web app