Tài liệuỨng dụng Java

Ứng dụng Java

Deploy Spring Boot, Quarkus và ứng dụng web Java khác bằng Maven hoặc Gradle, chỉnh heap JVM vừa với gói hosting, lắng nghe trên $PORT và xử lý lỗi khởi động.

ZoPanel build ứng dụng web Java từ dự án Maven hoặc Gradle, chạy file jar thu được như một dịch vụ của tài khoản hosting và đặt nginx kèm SSL phía trước. Dùng cho Spring Boot, Quarkus hoặc bất kỳ HTTP server Java nào nhận được cổng lúc khởi động.

Điều kiện cần

  • Quản trị viên đã cài các phiên bản Java mà ứng dụng cần ở mục Runtime: thẻ Java (OpenJDK + Maven) có một nút cho mỗi phiên bản OpenJDK mà gói hệ thống cung cấp (ví dụ OpenJDK 21). Maven được cài cùng phiên bản đầu tiên. Có thể cài song song nhiều phiên bản:

    Hệ điều hành Các phiên bản OpenJDK có sẵn
    Ubuntu 22.04, Ubuntu 24.04 17, 21, 25
    Debian 12 17
    Debian 13 21, 25

    Với phiên bản Java khác (ví dụ Java 21 trên Debian 12, hoặc Java 8), hãy deploy bằng Dockerfile.

  • ZoPanel không cài Gradle: gói gradle của các bản phân phối quá cũ so với yêu cầu của dự án hiện nay. Dự án Gradle phải có Gradle wrapper (gradlew và thư mục gradle/wrapper/) trong repository.

  • Gói hosting có tính năng Git deploy & ứng dụng và đủ RAM (MB) cho quá trình build và hai JVM (xem mục Bộ nhớ bên dưới).

ZoPanel nhận diện gì

Dự án được coi là Java khi thư mục gốc có pom.xml, build.gradle hoặc build.gradle.kts. ZoPanel đề xuất các lệnh sau:

Dự án Lệnh build Lệnh chạy
Maven mvn -B -q -DskipTests package (hoặc sh mvnw … khi có mvnw) java -Xmx512m -jar "<file jar đầu tiên trong target/>"
Gradle sh gradlew --no-daemon -q build -x test (bắt buộc có wrapper, xem bên dưới) java -Xmx512m -jar "<file jar đầu tiên trong build/libs/>"
Spring Boot (Maven hoặc Gradle) như trên; Gradle dùng task bootJar như trên, thêm --server.port=$PORT --server.address=127.0.0.1
Quarkus (Maven hoặc Gradle) như trên java -Xmx512m -Dquarkus.http.host=127.0.0.1 -Dquarkus.http.port=$PORT -jar target/quarkus-app/quarkus-run.jar (build/quarkus-app/… với Gradle)

File jar được chọn lúc khởi động bằng ls, bỏ qua các jar có tên kết thúc bằng -plain.jar (jar không kèm thư viện của Gradle), -sources.jar, -javadoc.jar, -tests.jar và -original.jar. Spring Boot được nhận ra khi pom.xml chứa spring-boot hoặc file build Gradle chứa org.springframework.boot; Quarkus được nhận ra khi pom.xml chứa quarkus-maven-plugin hoặc io.quarkus, hoặc file build Gradle chứa io.quarkus. Test được bỏ qua khi build.

Nếu không có gradlew, lệnh build đề xuất gọi gradle và deploy dừng với thông báo "this Gradle project has no Gradle wrapper…". Hãy chạy gradle wrapper trên máy của bạn, commit gradlew và gradle/wrapper/, rồi deploy lại.

Việc nhận diện chạy theo thứ tự cố định, nên hãy kiểm tra framework được nhận diện nếu repository trộn nhiều ngôn ngữ:

  • Nếu cùng thư mục có package.json hoặc composer.json, dự án được nhận là Node.js hoặc PHP. Gemfile cũng được xét trước Java.
  • Procfile có dòng web: sẽ thay lệnh chạy.
  • Với dự án nhiều module, đặt Thư mục gốc là module tạo ra ứng dụng web, hoặc tắt Tự nhận diện và tự viết lệnh.

Các framework khác như Micronaut được nhận là Java thông thường. Chúng build bình thường, nhưng hãy kiểm tra lệnh chạy (xem bên dưới).

Phiên bản Java

ZoPanel đọc phiên bản Java mà dự án yêu cầu và dùng OpenJDK đó để build và chạy ứng dụng. JAVA_HOME và PATH trỏ tới JDK đó trong lúc build (Maven, Gradle wrapper) và khi ứng dụng chạy:

Dự án Đọc từ
Maven <java.version>, <maven.compiler.release> hoặc <maven.compiler.source> trong pom.xml (1.8 nghĩa là 8)
Gradle JavaLanguageVersion.of(…), JavaVersion.VERSION_… hoặc sourceCompatibility trong build.gradle(.kts)

Log build ghi rõ lựa chọn ("Using OpenJDK 21"). Nếu phiên bản đó chưa được cài, hệ thống dùng JDK đã cài cũ nhất trong số các bản mới hơn, vì nó vẫn biên dịch và chạy được code cũ (dự án Java 8 và 11 build bằng OpenJDK 17). Nếu chỉ có JDK cũ hơn, deploy dừng với thông báo "Java 25 is not installed…": hãy cài phiên bản đó ở mục Runtime. Khi file build không ghi phiên bản, dùng JDK mới nhất đã cài. Muốn tự chọn, tắt Tự nhận diện và chọn Phiên bản. JAVA_HOME khai báo trong Biến môi trường sẽ ghi đè lựa chọn này.

Deploy ứng dụng Java

  1. Ở Website → Thêm website, chọn Git deploy, nhập tên miền và địa chỉ repository. Xem Git deploy cho repository riêng tư và webhook.
  2. Mở tab Deploy của website. Kiểm tra Framework và các lệnh trong Build & chạy.
  3. Muốn sửa lệnh, tắt Tự nhận diện, sửa Lệnh build hoặc Lệnh chạy, rồi bấm Lưu & deploy lại.
  4. Thêm cấu hình trong Biến môi trường (URL database, secret, profile).
  5. Bấm Deploy ngay và theo dõi quá trình build trong log tác vụ.

Bản mới chỉ được đưa lên khi trả lời Đường dẫn health check (mặc định /) với mã dưới 500 trong vòng 90 giây. Trong lúc đó bản cũ vẫn phục vụ khách truy cập. Lệnh cài đặt và lệnh build mỗi lệnh được chạy tối đa 30 phút.

Cổng và địa chỉ

Ứng dụng phải lắng nghe tại 127.0.0.1, trên cổng nằm trong biến môi trường PORT. ZoPanel đặt PORT mỗi lần khởi động và giá trị này khác nhau giữa hai slot blue/green (slot thứ hai dùng cổng gốc cộng 10000), nên đừng ghi cứng số cổng.

Spring Boot. Lệnh chạy đề xuất đã truyền --server.port=$PORT --server.address=127.0.0.1. Bạn cũng có thể khai báo trong application.properties:

server.port=${PORT}
server.address=127.0.0.1
# nginx gửi X-Forwarded-For và X-Forwarded-Proto: dùng chúng cho redirect và IP khách
server.forward-headers-strategy=native

Quarkus. Bản build Quarkus tạo target/quarkus-app/quarkus-run.jar, thư viện nằm trong target/quarkus-app/lib/ (build/quarkus-app/ với Gradle). Lệnh chạy đề xuất chạy file này và truyền địa chỉ, cổng:

java -Xmx512m -Dquarkus.http.host=127.0.0.1 -Dquarkus.http.port=$PORT -jar target/quarkus-app/quarkus-run.jar

Nếu bạn đóng gói thành uber-jar (quarkus.package.jar.type=uber-jar), hãy tắt Tự nhận diện và trỏ lệnh chạy tới file đó.

Server khác. Đọc biến trong code, ví dụ:

int port = Integer.parseInt(System.getenv("PORT"));

Bộ nhớ

Mọi thứ tài khoản chạy đều dùng chung RAM (MB) của gói: PHP, cron job, quá trình build Maven/Gradle và các JVM. Tiến trình vượt giới hạn sẽ bị kernel dừng, sau đó ZoPanel khởi động lại ứng dụng.

  • Lệnh chạy đề xuất đặt heap 512 MB bằng -Xmx512m. JVM dùng nhiều hơn heap (metaspace, stack của thread, code cache), nên tiến trình luôn lớn hơn giá trị -Xmx.
  • Khi deploy, quá trình build chạy trong lúc bản hiện tại vẫn phục vụ, và trong một thời gian ngắn bản mới và bản cũ chạy song song. Hãy tính RAM của gói đủ cho hai JVM cùng chạy, cộng thêm phần dư.
  • Muốn đổi heap, tắt Tự nhận diện và sửa -Xmx trong Lệnh chạy. Gói nhỏ thì giảm; chỉ tăng khi gói đủ chỗ cho gấp đôi giá trị đó.

Theo dõi RAM của tài khoản ở mục Tài nguyên, và RAM của ứng dụng ở thẻ trạng thái trong tab Deploy. Xem Gói hosting và giới hạn.

Biến môi trường

Các biến trong Biến môi trường dùng được khi build và khi chạy. ZoPanel đặt thêm PORT và HOST=127.0.0.1.

  • Tên biến gồm chữ, số và _, bắt đầu bằng chữ hoặc _, tối đa 64 ký tự. Giá trị nằm trên một dòng, tối đa 8.192 ký tự. Tối đa 200 biến.
  • Giá trị được lưu trong file chỉ root đọc được và được systemd truyền cho dịch vụ, không bao giờ nằm trên dòng lệnh.

Spring Boot đọc biến môi trường theo cơ chế relaxed binding: SPRING_DATASOURCE_URL đặt spring.datasource.url, SPRING_PROFILES_ACTIVE=prod chọn profile. Quarkus đọc các biến như QUARKUS_DATASOURCE_JDBC_URL theo cách tương tự.

Database tạo trong ZoPanel dùng host 127.0.0.1. Xem Database.

File và dữ liệu cố định

Ứng dụng chạy trong sandbox: chỉ ghi được trong thư mục home của tài khoản và thư mục /tmp riêng. Mỗi lần deploy tạo một thư mục release mới, nên file upload và dữ liệu cần giữ qua các bản phải nằm trong Đường dẫn lưu trữ cố định (ví dụ uploads) hoặc trong database. 5 bản release gần nhất được giữ lại để Rollback.

Log

  • Log ứng dụng trong tab Deploy hiển thị 400 dòng stdout và stderr mới nhất. Bật Trực tiếp để theo dõi liên tục.
  • Toàn bộ output Maven/Gradle của từng lần deploy nằm trong log tác vụ ở mục Tác vụ.
  • Access log và error log của nginx nằm ở tab Nhật ký của website.

Xử lý sự cố

Thông báo hoặc hiện tượng Cách xử lý
"Java is not installed — install it under Runtimes" Server chưa có JDK nào. Nhờ quản trị viên cài một phiên bản trên thẻ Java (OpenJDK + Maven) ở mục Runtime.
"Java 25 is not installed (installed: …)" Dự án yêu cầu Java mới hơn bản server đang có. Cài phiên bản đó ở mục Runtime nếu hệ điều hành có, hạ phiên bản Java của dự án, hoặc deploy bằng Dockerfile.
"this Gradle project has no Gradle wrapper…" Commit Gradle wrapper (gradlew, gradle/wrapper/) vào repository.
"OpenJDK 21 is not packaged for this system" khi cài Hệ điều hành không cung cấp phiên bản đó (xem bảng ở trên). Chọn phiên bản khác hoặc deploy bằng Dockerfile.
UnsupportedClassVersionError Jar được biên dịch cho Java mới hơn JDK đang chạy nó, thường do phiên bản bị đặt tay. Bật lại Tự nhận diện, hoặc chọn đúng Phiên bản.
Unable to access jarfile với tên rỗng Không có jar chạy được trong target/ hoặc build/libs/: kiểm tra output build, hoặc ghi rõ jar trong lệnh chạy.
"The app did not respond on port … within 90s (it must listen on $PORT)" Ứng dụng lắng nghe cổng cố định (thường là 8080) hoặc khởi động quá chậm. Lắng nghe trên $PORT, giảm việc lúc khởi động hoặc tăng CPU của gói.
"The app exited during startup" Xem Log ứng dụng: thường do thiếu biến, không kết nối được database, hoặc không tìm thấy jar (Unable to access jarfile).
java.lang.OutOfMemoryError: Java heap space Tăng -Xmx, trong phạm vi RAM của gói.
Ứng dụng tự khởi động lại mà không có lỗi Java Tài khoản chạm giới hạn RAM. Giảm -Xmx hoặc tăng RAM (MB) của gói.
Redirect về http:// hoặc ứng dụng thấy IP khách là 127.0.0.1 Cho framework tin các header forwarded (server.forward-headers-strategy=native với Spring Boot).

Xem thêm


← Ứng dụng Ruby và Rails Ứng dụng .NET →