App: project, service và deploy
Khái niệm
| Khái niệm | Ý nghĩa |
|---|---|
| Project | Một sản phẩm của bạn: gồm các service, database và bucket. Chạy ở một Vị trí chọn lúc tạo. |
| Environment | Một bản sao của project (mặc định production; thêm staging, hoặc pr-<số> cho preview). Mỗi environment có mạng riêng, biến riêng, database riêng hoặc dùng chung. |
| Service | Một chương trình chạy trong environment: web, worker, cron hoặc riêng tư (TCP). |
| Deploy | Một lần build và chạy service, đánh số #1, #2… |
Trên canvas của project, mỗi ô là một service, database hoặc bucket. Bấm vào ô để mở bảng chi tiết. Sắp xếp lại đặt các ô về vị trí mặc định.
Loại service
Đổi ở tab Cấu hình → Loại service, rồi deploy lại để áp dụng.
| Loại | Dùng cho | Tab có |
|---|---|---|
| Web | Nhận request HTTP, có địa chỉ HTTPS và tên miền riêng | Deploy, Log, Số liệu, Biến môi trường, Tên miền, Cấu hình |
| Worker | Xử lý hàng đợi, bot, tác vụ nền; không có cổng, không có địa chỉ | Deploy, Log, Số liệu, Biến môi trường, Cấu hình |
| Cron job | Chạy theo lịch rồi dừng: sao lưu, gửi báo cáo… | Lần chạy, Deploy, Biến môi trường, Cấu hình |
| Riêng tư (TCP) | Database hoặc server chỉ các service của bạn truy cập, tại <service>.internal:<cổng>; không có địa chỉ công khai |
Deploy, Log, Số liệu, Biến môi trường, Tên miền, Cấu hình |
Cron job
- Lịch chạy (cron): 5 trường
phút giờ ngày tháng thứ, giờ Việt Nam. Ví dụ0 2 * * *là 2 giờ sáng mỗi ngày,*/15 * * * *là mỗi 15 phút. ZoCloud đặt khoảng cách tối thiểu giữa hai lần chạy (portal báo nếu lịch dày quá). - Tối đa (phút): thời gian tối đa một lần chạy.
- Mỗi lần chạy là một container chạy tới khi xong, cùng biến môi trường và mạng của environment. Lần trước chưa xong thì lần sau bị bỏ qua.
- Tab Lần chạy hiện mã thoát và các dòng log cuối; nút Chạy ngay chạy tay.
Nguồn deploy
GitHub App
- Vào mục GitHub của tổ chức, bấm Kết nối GitHub.
- Trên GitHub, cài ZoCloud cho tài khoản cá nhân hoặc tổ chức, chọn mọi repo hoặc một số repo.
- Nếu bạn thuộc nhiều tổ chức ZoCloud, chọn tổ chức sẽ dùng các repo này ("Gắn GitHub vào tổ chức nào?"). Một bản cài GitHub chỉ gắn với một tổ chức ZoCloud.
- Đã cài từ trước: bấm Đã cài trước đó? Liên kết. Thêm repo sau: Thêm repo cho ZoCloud hoặc Chọn repo.
ZoCloud chỉ đọc mã nguồn (không ghi), dùng token ngắn hạn cho từng repo khi build, và ghi trạng thái deploy lên commit. Khi bật Tự deploy khi push (tab Cấu hình), mỗi lần push lên nhánh của service sẽ deploy đúng commit đó; push trong lúc đang build thì ZoCloud chờ rồi deploy bản mới nhất.
Ngắt kết nối một tài khoản GitHub làm các service dùng repo của nó không build được nữa.
Nếu portal báo "ZoCloud chưa bật kết nối GitHub", bạn vẫn deploy được từ URL Git công khai hoặc zo CLI.
URL Git công khai
Dán https://github.com/you/app (hoặc Git host khác qua https). Không tự deploy khi push: bấm Deploy hoặc dùng CLI.
Tải lên từ máy (zo CLI)
zo deploy đóng gói thư mục hiện tại và gửi lên. Không bao giờ gửi các file .env* (trừ .env.example), .git, node_modules, .venv…, và tôn trọng .gitignore, .zocloudignore, .dockerignore. Xem zo CLI và MCP server.
Docker image
Image công khai (Docker Hub, GHCR, Quay…). ZoCloud ghim tag về digest lúc deploy, nên rollback chạy lại đúng bản đó. Cổng để trống thì lấy từ EXPOSE của image.
Template
Thêm → Từ template: chọn ứng dụng (lọc theo nhóm hoặc Tìm template), bấm Deploy template. Portal lần lượt tạo project, database, service, biến (bí mật được sinh ngẫu nhiên), ổ lưu trữ rồi deploy.
Build và chạy
ZoCloud tự nhận diện framework và chọn lệnh cài, build, chạy. Muốn biết trước ZoCloud sẽ làm gì với một thư mục: zo detect.
Ghi đè ở tab Cấu hình → Build và chạy (để trống là dùng giá trị tự nhận diện; có hiệu lực từ lần deploy sau):
| Ô | Ghi chú |
|---|---|
| Nhánh, Thư mục gốc | Thư mục gốc để trống nếu app nằm ở gốc repo (monorepo: apps/web) |
| Lệnh cài đặt, Lệnh build, Lệnh chạy | |
| Cổng | App phải nghe trên biến PORT; để trống: theo EXPOSE hoặc 8080 |
| Kiểm tra sức khoẻ | Đường dẫn trả về mã < 500 khi app sẵn sàng (ví dụ /health); để trống: chỉ kiểm tra cổng |
| mCPU, RAM (MB) | Tài nguyên mỗi bản chạy, trong giới hạn gói |
| Watch paths | Mỗi dòng một mẫu tính từ gốc repo (api/**, *.go, !docs/**): chỉ deploy khi lần push đổi file khớp mẫu |
File cấu hình zocloud.json (hoặc railway.json)
Đặt ở gốc repo (hoặc thư mục gốc của service). Nếu có file, giá trị trong file được ưu tiên hơn các ô trên portal ở mỗi lần build; portal ghi rõ file nào đang áp dụng.
{
"build": {
"builder": "auto",
"dockerfile": "Dockerfile",
"install": "npm ci",
"build": "npm run build",
"runtime_version": "22",
"output_dir": "dist",
"watch_paths": ["api/**", "!**/*.md"]
},
"deploy": {
"start": "npm start",
"prestart": "npm run migrate",
"port": 3000,
"health_path": "/health",
"replicas": 2,
"cron_schedule": "0 2 * * *",
"sleep_after_minutes": 15
}
}
| Trường | Giá trị hợp lệ |
|---|---|
builder |
auto, dockerfile, generated |
dockerfile |
đường dẫn trong repo |
prestart |
lệnh chạy trước khi app khởi động (ví dụ migration) |
port |
1–65535 |
health_path |
bắt đầu bằng / |
replicas |
0–20 |
cron_schedule |
biểu thức cron (chỉ cho service cron) |
sleep_after_minutes |
0 (không bao giờ ngủ) hoặc 5–1440 |
watch_paths |
tối đa 50 mẫu |
zocloud.json không chấp nhận trường lạ (sai tên là deploy báo lỗi). Mỗi lệnh là một dòng.
Chuyển từ Railway: ZoCloud đọc railway.json với các trường builder, buildCommand, dockerfilePath, watchPatterns, startCommand, preDeployCommand, healthcheckPath, numReplicas, cronSchedule, sleepApplication.
Biến môi trường
Tab Biến môi trường: Thêm biến, hoặc Sửa dạng .env để dán nhiều dòng; Dạng bảng để quay lại. Biến được mã hoá khi lưu, dùng cả lúc build và lúc chạy, có hiệu lực từ lần deploy sau.
Biến tham chiếu
Giá trị có thể trỏ tới database, bucket hay service khác trong cùng environment, và tự cập nhật khi nguồn thay đổi:
| Tham chiếu | Ý nghĩa |
|---|---|
${{pg.DATABASE_URL}} |
chuỗi kết nối của database tên pg |
${{cache.REDIS_URL}} |
Valkey tên cache |
${{files.S3_BUCKET}}, ${{files.S3_ACCESS_KEY_ID}}… |
bucket tên files |
${{api.PRIVATE_URL}} |
http://api.internal (mạng nội bộ) |
${{api.PUBLIC_URL}} |
https://…zocloud.app của web service api |
${{api.TÊN_BIẾN}} |
biến (không phải tham chiếu) của service api |
Biến do ZoCloud đặt
PORT, ZOCLOUD_SERVICE_NAME, ZOCLOUD_PUBLIC_DOMAIN, ZOCLOUD_DEPLOYMENT_ID, ZOCLOUD_GIT_COMMIT_SHA (khi build từ Git), ZOCLOUD_VOLUME_MOUNT_PATH (khi có volume). Bạn không đặt được các biến này.
Mạng nội bộ
Các service trong cùng environment gọi nhau qua mạng riêng, không ra Internet:
- Web service:
http://<service>.internal(HTTP và WebSocket). Dùng biến${{<service>.PRIVATE_URL}}. - Service Riêng tư (TCP):
<service>.internal:<cổng>cho giao thức TCP bất kỳ (biếnPRIVATE_DOMAIN,PRIVATE_PORT).
Địa chỉ nội bộ hiện ở tab Tên miền của service. Service gọi tới cần được deploy lại sau khi bạn thêm biến.
Volume (ổ lưu trữ bền)
Cho file tải lên, SQLite… Dữ liệu giữ nguyên qua các lần deploy. Mỗi service có tối đa một volume.
- Tab Cấu hình → Volume → Thêm volume: nhập Đường dẫn trong container (ví dụ
/data) và Dung lượng (MB). - Deploy lại để gắn volume.
Lưu ý:
- Service có volume chạy 1 bản, không tự scale. Mỗi lần deploy, bản cũ dừng trước khi bản mới chạy (gián đoạn vài giây).
- Đổi dung lượng chỉ tăng được, không giảm; làm online. Volume đầy thì app nhận lỗi "No space left".
- Dung lượng đã dùng được đo khoảng 10 phút một lần. Tổng dung lượng volume là một giới hạn của gói.
- Xóa volume: dữ liệu bị xóa sau lần deploy kế tiếp và không khôi phục được.
Sao lưu volume
- Tự động mỗi đêm (mã hoá, bản chính lưu tại Việt Nam), thêm các bản dày (mỗi vài phút), và nút Sao lưu ngay.
- Khôi phục một bản: toàn bộ file hiện có trong volume bị thay thế, service khởi động lại.
- Lệnh chạy quanh lần backup (cho database chạy trong container): Trước khi backup và Sau khi backup (luôn chạy), chạy bằng
sh -ctrong container với biến của service. Nếu lệnh trước lỗi thì không tạo bản backup. - Nếu máy chủ chứa volume gặp sự cố kéo dài, ZoCloud tự khôi phục bản sao lưu mới nhất sang máy khác và chạy service ở đó. Phần ghi sau bản sao lưu gần nhất có thể bị mất (thường tối đa khoảng 15 phút); liên hệ Hỗ trợ nếu bạn cần lấy lại phần đó.
Scale
Tab Cấu hình → Số bản chạy:
- Số bản chạy (0–20): áp dụng ngay, không cần deploy. Từ 2 bản trở lên, app không gián đoạn khi một máy gặp sự cố; app 1 bản có thể gián đoạn vài phút khi máy của nó hỏng. Nên dùng 2 bản cho production.
- Tự động scale theo CPU: đặt Tối thiểu, Tối đa, CPU mục tiêu (%). ZoCloud thêm bản chạy khi CPU trung bình vượt mục tiêu và bớt khi tải giảm, trong giới hạn gói. Không áp dụng cho service có volume hoặc cron.
Tab Số liệu: Request, Lỗi (5xx), Độ trễ p95, CPU, RAM của mọi bản chạy, cập nhật mỗi phút.
Ngủ khi không có truy cập
Chỉ cho web service. Tab Cấu hình → Ngủ khi không có truy cập:
- Theo gói: theo mặc định của gói bạn đang dùng.
- Không bao giờ ngủ.
- Ngủ sau 10 / 30 / 60 / 240 phút.
Khi ngủ, app tắt (không tốn tài nguyên); request kế tiếp tự đánh thức app sau vài giây. Hợp với app demo, nội bộ, ít người dùng. Không nên dùng cho app cần phản hồi tức thì.
Environment
Trên canvas, mở menu môi trường (cạnh production):
- Tạo environment: nhập Tên (ví dụ
staging), chọn Sao chép từ environment nào, Nhánh Git (để trống để giữ nhánh của từng service). Environment mới có cùng service, biến, volume; push lên nhánh đó là tự deploy. - Database riêng (trống): tạo database trống giống bản gốc, không đụng dữ liệu production. Không chọn thì environment mới không có database của riêng nó: hãy tự thêm database cho environment đó (biến tham chiếu chỉ trỏ tới database cùng environment).
- Xoá environment: service và database riêng của nó bị xoá.
Preview cho Pull Request
Cần repo kết nối qua GitHub App.
- Menu môi trường → Preview cho Pull Request → Bật preview.
- Chọn Database của preview:
- Database riêng, trống: mỗi PR có bản sao trống của các database production (cùng tên, không có dữ liệu), xóa khi đóng PR. Tính vào giới hạn gói.
- Dùng chung database production: nhanh, nhưng PR chạm được dữ liệu thật.
- Không có database.
Mỗi PR vào nhánh mà project deploy có environment pr-<số> riêng, địa chỉ <service>-pr<số>-<project>.zocloud.app, chạy 1 bản, cập nhật theo mỗi lần push và tự xóa khi PR đóng hoặc merge. GitHub hiện trạng thái "ZoCloud preview / " trên PR, bấm vào mở thẳng bản preview. PR từ fork không có preview (vì preview chạy với biến môi trường của project). Xoá tay: chọn environment preview → Xóa preview.
Deploy, log và rollback
Tab Deploy
Liệt kê các lần deploy với nguyên nhân (Đẩy code, Deploy từ CLI, Đổi cấu hình, Quay lại bản cũ…), commit và trạng thái. Bấm Deploy ở góc trên để deploy lại.
Bản đang chạy vẫn phục vụ khi bản mới lỗi; traffic chỉ chuyển sang khi bản mới khoẻ.
Rollback
Ở tab Deploy, chọn một bản cũ → Quay lại bản này. Không cần build lại. CLI: zo rollback <số>.
Tab Log
- Ô Tìm trong log (Enter): tìm theo chữ.
- Bộ lọc: Tất cả, Output của app,
stderr, Request HTTP (lọc thêm 2xx/3xx/4xx/5xx; mỗi dòng có status, method, path, thời gian xử lý, IP), Tường lửa (sự kiện WAF). - Khoảng thời gian: 15m, 1h, 6h, 24h, 7d.
- Tạm dừng / Theo dõi trực tiếp.
Lỗi deploy thường gặp
| Hiện tượng | Nguyên nhân hay gặp |
|---|---|
| Không clone được repo | Repo không công khai (dùng GitHub App), sai nhánh hoặc sai URL |
| Build lỗi | Xem log build ở tab Deploy; thử zo detect trên máy |
| App khởi động rồi thoát | App không nghe 0.0.0.0:$PORT, thiếu biến môi trường |
| Hết tài nguyên / vượt giới hạn gói | Giảm RAM/bản chạy hoặc nâng gói (Thanh toán) |
Tên miền riêng
Chỉ cho web service. Địa chỉ ….zocloud.app luôn có sẵn, HTTPS.
-
Tab Tên miền → nhập tên (ví dụ
www.example.vn) → Thêm. -
Chứng minh tên miền là của bạn (nếu portal yêu cầu): thêm bản ghi TXT
Loại Tên Giá trị TXT _zocloud.<tên-miền>zocloud-verify=<mã của tổ chức>Có thể đặt trên chính tên miền hoặc tên miền cha: chứng minh
example.vnlà đủ cho mọi tên bên dưới. Không cần làm bước này nếu tên miền mua tại ZoCloud, dùng ZoCloud DNS, hoặc thuộc zone Cloudflare đã kết nối. -
Trỏ tên miền về ZoCloud:
- Tên con (
www,app…):CNAME→<service>-<project>.zocloud.app(portal hiện đúng giá trị). - Tên gốc (
example.vn): bản ghiAvề các IP mà portal hiện (trang Tên miền → Gắn tên miền). Xoá các bản ghi A/AAAA cũ của tên gốc, và nên thêmwww(CNAME về tên gốc).
- Tên con (
-
ZoCloud kiểm tra DNS mỗi phút. Khi DNS đúng, trạng thái chuyển từ chờ DNS sang hoạt động và chứng chỉ HTTPS được cấp tự động trong vài phút, gia hạn tự động.
Tên miền dùng ZoCloud DNS hoặc Cloudflare đã kết nối: bản ghi được tạo tự động. Xem Tên miền. CLI: zo domains add www.example.vn.
Bảo mật (tường lửa và chặn truy cập)
Chỉ cho web service. Tab Cấu hình → Bảo mật. Áp cho mọi tên miền của service.
Tường lửa (OWASP Core Rule Set, đứng trước app):
| Chế độ | Tác dụng |
|---|---|
| Tắt | Request tới app không qua kiểm tra |
| Chỉ ghi nhận (mặc định) | Tấn công (SQL injection, XSS, dò quét…) được ghi vào log (lọc Tường lửa), không chặn |
| Chặn | Tấn công bị từ chối với mã 403 trước khi tới app |
Cách làm khuyến nghị: để Chỉ ghi nhận vài ngày, xem log Tường lửa có báo nhầm không, rồi chuyển sang Chặn. ZoCloud gợi ý khi service đã sẵn sàng.
- Ứng dụng: chọn WordPress, Drupal, Nextcloud để dùng các ngoại lệ có sẵn (nếu không, trang quản trị và trình soạn thảo dễ bị báo nhầm), hoặc Khác.
- Luật đã tắt: số hiệu luật (lấy từ dòng log tường lửa) đang chặn nhầm, cách nhau bằng dấu phẩy, ví dụ
942100, 920350. - Quốc gia bị chặn: mã hai chữ cái (
CN, RU…). Khách từ đó nhận trang 403. - Địa chỉ bị chặn: mỗi dòng một IP hoặc dải mạng (
203.0.113.7,198.51.100.0/24).
Bấm Lưu.
Xoá service
Tab Cấu hình → Vùng nguy hiểm → Xoá service, gõ tên service để xác nhận. App dừng và tên miền thôi phục vụ.