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

Ứng dụng Python

Deploy ứng dụng Django, Flask và FastAPI với môi trường ảo, worker gunicorn hoặc uvicorn theo cấu hình gói, file tĩnh, migration và log.

ZoPanel chạy ứng dụng web Python như một dịch vụ của tài khoản hosting, phía sau nginx. Mỗi bản release có môi trường ảo riêng trong .venv, app server (gunicorn hoặc uvicorn) được cài thêm nếu thiếu, và số worker tính theo CPU, RAM của gói. Trang này nói về những điểm riêng của Python; quy trình deploy chung được mô tả ở Git deploy.

Điều kiện cần

  • Máy chủ có bộ công cụ Python. Trình cài đặt mặc định đã cài; nếu chưa, quản trị viên mở Runtime, tìm thẻ Python ở mục Runtime khác và bấm Cài đặt. Thao tác này cài python3, python3-venv, python3-pip, python3-dev, build-essential, libpq-dev và pkg-config.
  • Một website loại Git deploy, hoặc bất kỳ website nào có tab Deploy.
  • Gói hosting của tài khoản phải có Git deploy & ứng dụng.

Phiên bản Python

Mặc định ứng dụng dùng Python 3 đi kèm hệ điều hành:

Hệ điều hành Python
Ubuntu 22.04 3.10
Ubuntu 24.04 3.12
Debian 12 3.11
Debian 13 3.13

Để build ứng dụng bằng Python khác, quản trị viên cài uv ở mục Runtime (thẻ uv (Python versions)). ZoPanel tải bản phát hành của uv và kiểm tra nó với checksum SHA-256 được công bố kèm theo. Sau đó:

  • Ô Phiên bản của ứng dụng chọn Python. Tự nhận diện lấy giá trị từ .python-version (3.12 hay 3.12.4 đều là 3.12); khi tắt Tự nhận diện, chọn ở Phiên bản (có từ 3.10 đến 3.14).
  • Trong lúc build, uv cài Python đó cho tài khoản hosting, dưới quyền tài khoản đó, trong thư mục home của nó (khoảng 100 MB mỗi phiên bản, tải một lần và dùng lại cho các lần build sau). uv kiểm tra mỗi lần tải với checksum được ghi sẵn trong uv. Sau đó lệnh python3 -m venv .venv của lệnh cài đặt tạo môi trường ảo bằng Python này.
  • Log build ghi rõ Python được dùng, ví dụ "Using Python 3.13 (managed by uv; the system Python is 3.12)" hoặc "Using the system Python 3.12".

Khi không có uv, .python-version yêu cầu phiên bản khác sẽ bị bỏ qua và log build ghi rõ: "Python 3.13 was requested (.python-version or Version), but only the system Python 3.12 is available: building with 3.12…". Các giá trị uv không cài được (ví dụ pypy3.10) cũng bị bỏ qua kèm ghi chú. Với trình thông dịch mà cả hai cách đều không cung cấp, hãy deploy bằng Dockerfile (xem Deploy bằng Docker).

Nhận diện

Repository được xem là Python khi có manage.py, requirements.txt, pyproject.toml hoặc Pipfile, và không có các file được kiểm tra trước: package.json, composer.json, Gemfile, pom.xml/build.gradle hoặc file *.csproj.

Ứng dụng web Python có thêm package.json cho công cụ front-end (Tailwind, Vite, esbuild) vẫn được nhận diện là Python khi thỏa cả hai điều kiện:

  • repository có manage.py, hoặc requirements.txt, pyproject.toml hay Pipfile có nhắc tới django, flask, fastapi, uvicorn hoặc gunicorn;
  • package.json không có script start và không dùng framework server Node nào (Next.js, Nuxt, NestJS, Express, Fastify, Koa, Hono, Remix, SvelteKit, Astro).

Nếu package.json có script build, tài nguyên front-end được build trước: npm ci && npm run build (hoặc npm install && npm run build khi không có package-lock.json) được đặt trước lệnh build, và Node.js phải được cài ở mục Runtime. Ngược lại, repository sẽ bị nhận diện là Node.js: hãy tắt Tự nhận diện, đặt Runtime là python và tự điền các lệnh bên dưới.

Lệnh cài đặt

File tìm thấy Lệnh cài đặt
requirements.txt python3 -m venv .venv && .venv/bin/pip install --upgrade pip -q && .venv/bin/pip install -r requirements.txt
pyproject.toml python3 -m venv .venv && .venv/bin/pip install --upgrade pip -q && .venv/bin/pip install .
Pipfile python3 -m venv .venv && .venv/bin/pip install pipenv -q && .venv/bin/pipenv install --deploy --system

Nếu file thư viện không nhắc tới app server mà framework cần, hệ thống nối thêm && .venv/bin/pip install gunicorn (Django, Flask) hoặc && .venv/bin/pip install uvicorn (FastAPI). Cache tải về của pip được giữ trong tài khoản nên các lần build sau nhanh hơn.

Framework và lệnh chạy

Nhận diện khi Framework Lệnh chạy đề xuất
có manage.py, hoặc django trong danh sách thư viện Django .venv/bin/gunicorn <project>.wsgi:application --bind 127.0.0.1:$PORT
fastapi trong danh sách thư viện FastAPI .venv/bin/uvicorn <module>:<app> --host 127.0.0.1 --port $PORT
flask trong danh sách thư viện Flask .venv/bin/gunicorn <module>:<app> --bind 127.0.0.1:$PORT
còn lại Python .venv/bin/python main.py (hoặc app.py, server.py)
  • Django: <project> là thư mục đầu tiên chứa wsgi.py (nếu không có thì là config). Lệnh build là .venv/bin/python manage.py collectstatic --noinput || true.
  • FastAPI và Flask: ZoPanel tìm dòng như app = FastAPI( hoặc app = Flask( trong main.py, app.py, server.py, app/main.py, src/main.py, wsgi.py hoặc api.py, rồi dùng dạng module:biến (ví dụ app.main:app). Không tìm thấy thì dùng main:app.
  • Nếu có Procfile với dòng web:, dòng đó luôn được dùng làm lệnh chạy.

Bấm Phân tích repository trong tab Deploy để kiểm tra kết quả trước khi deploy.

Deploy ứng dụng

  1. Vào Website → Thêm website, chọn Git deploy, nhập Địa chỉ repository, Nhánh và, nếu ứng dụng nằm trong thư mục con, Thư mục gốc. Bấm Tạo website.
  2. Thêm cấu hình (URL database, secret key, allowed hosts) ở Biến môi trường trong tab Deploy rồi bấm Lưu & deploy lại.
  3. Muốn đổi lệnh, tắt Tự nhận diện trong Build & chạy, sửa lệnh rồi bấm Lưu & deploy.

Môi trường khi chạy

Lệnh chạy được thực thi từ thư mục release với:

Biến Giá trị
PORT Cổng của slot. Gắn server vào 127.0.0.1:$PORT.
HOST 127.0.0.1
VIRTUAL_ENV, PATH .venv của bản release, đứng đầu PATH, nên gunicorn và python trỏ vào môi trường ảo.
PYTHONUNBUFFERED 1, để print() và logging hiện ra ngay trong log.
WEB_CONCURRENCY Số worker, trừ khi bạn tự đặt: 2 × số CPU gói cho phép + 1, tối đa một worker cho mỗi 128 MB RAM của gói (tối thiểu 2), không quá 32.

Cả gunicorn và uvicorn đều lấy WEB_CONCURRENCY làm số worker mặc định. Tuỳ chọn --workers trong lệnh chạy được ưu tiên hơn.

Biến môi trường

Các biến trong thẻ Biến môi trường dùng được trong lệnh cài đặt, lệnh build và khi chạy (tối đa 200 biến, giá trị một dòng). Dùng Dán .env để thêm nhiều biến một lúc. Đọc biến bằng os.environ:

import os
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
DEBUG = os.environ.get("DJANGO_DEBUG", "") == "1"
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "").split(",")

Django phía sau nginx

nginx xử lý SSL và chuyển request kèm header X-Forwarded-Proto. Thêm vào settings.py:

ALLOWED_HOSTS = ["example.com", "www.example.com"]
CSRF_TRUSTED_ORIGINS = ["https://example.com", "https://www.example.com"]
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")

Thiếu CSRF_TRUSTED_ORIGINS, form gửi qua HTTPS sẽ bị lỗi 403 CSRF.

File tĩnh

Với website proxy, mọi request, kể cả /static/, đều đi tới ứng dụng. Hãy phục vụ file tĩnh ngay trong ứng dụng bằng WhiteNoise:

  1. Thêm whitenoise vào requirements.txt.
  2. Thêm "whitenoise.middleware.WhiteNoiseMiddleware" ngay sau SecurityMiddleware trong MIDDLEWARE.
  3. Đặt STATIC_ROOT = BASE_DIR / "staticfiles".

Lệnh build được nhận diện chạy collectstatic ở mỗi lần deploy. Lệnh kết thúc bằng || true nên lỗi không làm dừng deploy: nếu trang mất CSS, hãy xem log build ở Tác vụ.

File người dùng tải lên

File ghi vào thư mục release sẽ mất ở lần deploy sau. Hãy thêm thư mục media vào Đường dẫn lưu trữ cố định (ví dụ media), hoặc lưu file tải lên vào S3 bằng django-storages và Lưu trữ S3 của ZoPanel. Khi DEBUG tắt, Django không tự phục vụ MEDIA_ROOT, nên nếu dùng thư mục lưu cố định bạn cần thêm view hoặc cấu hình WhiteNoise để phục vụ nó.

Migration

ZoPanel không tự chạy migration. Hãy thêm vào Lệnh build, lệnh này chạy cùng biến môi trường của bạn:

.venv/bin/python manage.py collectstatic --noinput && .venv/bin/python manage.py migrate --noinput

Với Flask-Migrate dùng .venv/bin/flask db upgrade, với Alembic dùng .venv/bin/alembic upgrade head.

Quan trọng: migration chạy trước khi bản mới đạt health check, trong lúc bản cũ vẫn đang phục vụ, và Rollback không hoàn tác migration. Hãy giữ migration tương thích ngược (thêm cột trước, xoá cột ở bản sau).

Phát hành không gián đoạn, rollback và log

Như mọi ứng dụng server, bản release Python khởi động ở slot rảnh và chỉ nhận lưu lượng khi Đường dẫn health check (mặc định /) trả về mã dưới 500 trong vòng 90 giây. Mã 400 hay 404 vẫn đạt; mã 500 thì không. Thẻ Các bản release giữ 5 bản build gần nhất để Rollback.

  • Log ứng dụng trong tab Deploy hiển thị 400 dòng mới nhất; bật Trực tiếp để theo dõi.
  • Log build nằm ở Tác vụ; log nginx ở tab Nhật ký.

Mỗi bản release có .venv riêng, được tạo lại ở mỗi lần deploy. Hãy lưu dữ liệu ở database hoặc đường dẫn lưu trữ cố định, đừng lưu trong .venv hay thư mục release.

Xử lý sự cố

Thông báo hoặc hiện tượng Nguyên nhân và cách xử lý
the app did not respond on port … within 90s (it must listen on $PORT) Server gắn vào địa chỉ hoặc cổng khác. Dùng --bind 127.0.0.1:$PORT (gunicorn) hoặc --host 127.0.0.1 --port $PORT (uvicorn).
the app exited during startup Xem Log ứng dụng. Nguyên nhân thường gặp: sai module:app trong lệnh chạy, thiếu biến môi trường, lỗi import.
install failed: … kèm No module named venv hoặc ensurepip is not available Thiếu bộ công cụ Python. Quản trị viên cài Python ở Runtime.
Log build ghi "only the system Python … is available" Dự án yêu cầu Python khác trong .python-version. Nhờ quản trị viên cài uv ở mục Runtime, hoặc xóa .python-version nếu Python của hệ thống là đủ.
could not install Python 3.x with uv uv không tải được Python đó (không có mạng, phiên bản không tồn tại, hoặc tài khoản đã hết dung lượng đĩa). Đọc các dòng phía trên trong log build.
install failed: … khi build mysqlclient Chưa cài header của MySQL client. Dùng PyMySQL, hoặc nhờ quản trị viên chạy apt-get install -y default-libmysqlclient-dev pkg-config.
Failed to find attribute 'app' in 'main' Đối tượng ứng dụng có tên hoặc module khác. Sửa lệnh chạy, ví dụ .venv/bin/gunicorn myapp.wsgi:app --bind 127.0.0.1:$PORT.
Django trả về Bad Request (400) với tên miền Thêm tên miền vào ALLOWED_HOSTS.
Trang không có CSS File tĩnh chưa được phục vụ: cài WhiteNoise và kiểm tra collectstatic chạy thành công trong log build.
Ứng dụng bị dừng khi tải cao Quá nhiều worker so với RAM của gói. Đặt WEB_CONCURRENCY thấp hơn trong Biến môi trường.

Xem thêm


← Ứng dụng Node.js Ứng dụng PHP →