Atpakaļ uz blogu
Augusts 19, 2026Ceļveži

Kā palaist Python lietotnes ar Gunicorn un Nginx VPS serverī

Izvietojiet Flask vai FastAPI lietotni Ubuntu ar virtualenv, Gunicorn systemd pakalpojumu, Nginx reverso starpnieku, TLS, vides failiem, žurnalizēšanu un 502 kļūdu un strādnieku izmēra kontrolsarakstu.

Kā palaist Python lietotnes ar Gunicorn un Nginx VPS serverī

Iebūvētais Flask serveris un uvicorn --reload ir izstrādei. Publiskā VPS vēlaties procesu pārvaldnieku, kas restartē strādniekus, piesaista localhost un sēž aiz reversā starpnieka, kas apstrādā TLS un lēnus klientus. Gunicorn ir parastā WSGI izvēle Flask un Django. FastAPI var darboties zem Gunicorn ar Uvicorn strādnieku klasi. Nginx (vai Caddy) pabeidz HTTPS un pārsūta uz 127.0.0.1:8000.

Šis ceļvedis iet cauri izkārtojumam, kas pārdzīvo restartēšanas: projekts /srv/app, virtualenv, .env ar noslēpumiem, gunicorn.service vienība, Nginx servera bloks, Let's Encrypt un žurnāla faili, ko patiešām varat grepēt. Runāsim arī par strādnieku skaitu, taimautiem un kāpēc 502 Bad Gateway gandrīz nekad nav «Nginx ir salūzis» — gandrīz vienmēr Gunicorn nedarbojas, ir piesaistīts nepareizai ligzdai vai avarē importā. Piemērs izmanto Flask ar piezīmēm FastAPI, kur komanda atšķiras.

Kāpēc šis steks

Gunicorn iepriekš sazarojas strādnieku procesos. Katrs strādnieks apstrādā vienu pieprasījumu vienlaikus, ja vien neizmantojat citu strādnieku klasi. Nginx buferē lēnus klientus, lai strādnieki neiestrēgtu, sūtot baitus mobilajam tīklam. systemd restartē lietotni, ja tā nomirst. Kopā tas ir garlaicīgi, kas ir tas, ko vēlaties trešajā naktī.

  • Gunicorn: stabils WSGI/ASGI procesu modelis
  • systemd: palaišana sāknēšanā, restartēšana avārijā, journald žurnāli
  • Nginx: TLS, statiski faili, pieprasījuma izmēra limiti, gzip
  • venv: sistēmas Python paliek tīrs
  • localhost piesaiste: lietotne sasniedzama tikai caur Nginx

Prasības

Python 3.10+ Ubuntu 22.04/24.04 der. Nepalaižiet pip kā root sistēmas site-packages. TLS vajag domēnu. Ja starpniekam dodat priekšroku Caddy, šī raksta Gunicorn vienība paliek tāda pati — mainās tikai priekšgala konfigurācija (skatiet Caddy rakstu).

  • Ubuntu 22.04 vai 24.04 VPS
  • Jūsu lietotne ar requirements.txt vai ekvivalentu
  • WSGI ieejas punkts (Flask: app:app) vai ASGI (FastAPI: app:app ar uvicorn strādniekiem)
  • Domēna A ieraksts HTTPS

1. solis: sistēmas pakotnes, lietotājs un projekta katalogs

Izveidojiet sistēmas lietotāju, kas nevar pieteikties interaktīvi, piederēt kodam un palaist Gunicorn. python3-venv un būvēšanas rīku instalēšana izvairās no pip kļūmēm pakotnēs, kas joprojām kompilē C paplašinājumus.

bash
ssh root@YOUR_VPS_IP
apt update && apt -y upgrade
apt -y install python3 python3-venv python3-pip python3-dev build-essential nginx curl

adduser --system --group --home /srv/app appuser
mkdir -p /srv/app
chown appuser:appuser /srv/app

# Copy your code (example):
# rsync -a --delete ./myproject/ appuser@YOUR_VPS_IP:/srv/app/

2. solis: Virtualenv un atkarības

Izveidojiet venv kā appuser, lai failu piederība būtu pareiza. Ražošanā piesieniet versijas. Pēc instalācijas apstipriniet, ka varat importēt lietotni vienreizējā gunicorn --check-config vai Python importā. Importa kļūdas šeit ir tās pašas kļūdas, kas vēlāk kļūst par 502.

bash
sudo -u appuser -H bash -lc '
cd /srv/app
python3 -m venv /srv/app/venv
/srv/app/venv/bin/pip install --upgrade pip
/srv/app/venv/bin/pip install -r /srv/app/requirements.txt gunicorn
'

# Flask example check:
sudo -u appuser -H /srv/app/venv/bin/python -c "from app import app; print('import ok')"

3. solis: vides fails

Nekodējiet SECRET_KEY vai datubāzes URL systemd vienībā tā, ka tie nonāk visiem lasāmā git. Izmantojiet EnvironmentFile. chmod 640, īpašnieks root, grupa appuser (vai īpašnieks appuser, ja tā vēlaties).

bash
cat >/srv/app/.env <<'EOF'
FLASK_ENV=production
SECRET_KEY=replace-with-openssl-rand-hex-32
DATABASE_URL=postgresql://app:password@127.0.0.1:5432/app
EOF
chown appuser:appuser /srv/app/.env
chmod 600 /srv/app/.env

4. solis: Gunicorn systemd pakalpojums

Piesaistiet 127.0.0.1:8000, ne 0.0.0.0, ja vien nav iemesla izlaist Nginx. Strādnieku skaits bieži ir (2 x CPU) + 1 sinhronajiem strādniekiem; 2 vCPU VPS tas ir 5, kas var būt par daudz, ja katrs strādnieks ielādē smagu ML modeli — tad izmantojiet 2–3. FastAPI iestatiet --worker-class uvicorn.workers.UvicornWorker un instalējiet uvicorn. Taimautiem jāpārsniedz lēnākais godīgais pieprasījums, ne 30 sekundes, ja jums ir 2 minūšu eksports.

bash
cat >/etc/systemd/system/gunicorn.service <<'EOF'
[Unit]
Description=Gunicorn for the web app
After=network.target

[Service]
User=appuser
Group=appuser
WorkingDirectory=/srv/app
EnvironmentFile=/srv/app/.env
ExecStart=/srv/app/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 --timeout 60 --access-logfile - --error-logfile - app:app
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now gunicorn
systemctl status gunicorn --no-pager
ss -tulpn | grep 8000

5. solis: Nginx reversais starpnieks un TLS

Nginx klausās 80/443 un starpnieko uz Gunicorn. client_max_body_size ir svarīgs augšupielādēm. proxy_read_timeout jāatbilst vai jāpārsniedz Gunicorn taimautam. Kad servera bloks darbojas HTTP, izsniedziet sertifikātu ar Certbot (vai nomainiet priekšgalu uz Caddy). Tālāk esošais fragments ir tikai HTTP, lai varētu testēt; pēc tam palaidiet Certbot, kas var rediģēt failu.

bash
cat >/etc/nginx/sites-available/app <<'EOF'
server {
    listen 80;
    server_name app.example.com;
    client_max_body_size 20m;

    location /static/ {
        alias /srv/app/static/;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 90s;
    }
}
EOF

ln -sf /etc/nginx/sites-available/app /etc/nginx/sites-enabled/app
nginx -t && systemctl reload nginx

ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw enable

apt -y install certbot python3-certbot-nginx
certbot --nginx -d app.example.com

6. solis: statiski faili, atļaujas un Flask/FastAPI īpatnības

Nginx jāapkalpo statiskie faili, ja varat; tas ir ātrāk nekā Gunicorn. Django collectstatic, Flask send_from_directory sīkām lietotnēm vai CDN vēlāk. appuser jāspēj lasīt koku. Ja izmantojat FastAPI, instalējiet uvicorn[standard] venv un mainiet ExecStart, lai izmantotu UvicornWorker. Ja TCP vietā izmantojat Unix ligzdas, vērsiet proxy_pass uz ligzdu un saskaņojiet atļaujas, lai www-data varētu tur rakstīt.

bash
# FastAPI ExecStart example:
# ExecStart=/srv/app/venv/bin/gunicorn -k uvicorn.workers.UvicornWorker --workers 2 --bind 127.0.0.1:8000 app:app

# Unix socket variant:
# --bind unix:/run/gunicorn/app.sock
# Nginx: proxy_pass http://unix:/run/gunicorn/app.sock:

chown -R appuser:appuser /srv/app

Strādnieki, atmiņa un nulles dīkstāves pārlādēšana

Sinhronie Gunicorn strādnieki ir vienkārši un pietiek CPU vieglām request/response API. Ja vajag daudz vienlaicīgu lēnu I/O gaidīšanu, apsveriet gevent vai ASGI strādnieku — mēriet, neminiet. Katrs strādnieks ielādē jūsu lietotni; RAM ~= strādnieki reiz lietotnes RSS. 2 GB VPS ar 8 strādniekiem 300 MB lietotnei sāks swappot un justies «nejauši lēni». systemctl reload gunicorn (HUP) var restartēt strādniekus ar jauno kodu, ja izvietojāt failus uz vietas; pilna restartēšana ir skaidrāka, kad mainās atkarības.

bash
# After git pull / rsync of new code:
sudo -u appuser -H /srv/app/venv/bin/pip install -r /srv/app/requirements.txt
systemctl restart gunicorn
curl -I https://app.example.com/health

502 un klusu avāriju novēršana

502 nozīmē, ka Nginx nesaņēma derīgu atbildi no upstream. journalctl -u gunicorn -e ir pirmā komanda. Parastie cēloņi: nepareizs module:app nosaukums, trūkstoša .env atslēga, Postgres nedarbojas, piesaistīts 127.0.0.1, bet Nginx citā resursdatorā, SELinux (reti Ubuntu) vai lietotne klausās tikai IPv6. 504 ir taimauts. 301 cilpas notiek, kad lietotne novirza uz HTTP, kamēr X-Forwarded-Proto ignorē.

  • systemctl status gunicorn — vai tas ir aktīvs?
  • journalctl -u gunicorn -n 100 — ImportError, trūkstoša env, datubāze
  • curl -v http://127.0.0.1:8000/ no VPS — ja tas neizdodas, Nginx ir nevainīgs
  • nginx -t un error.log — upstream prematurely closed connection
  • ss -tulpn | grep 8000 — nekas neklausās
  • Disks pilns — strādnieki avarē noslēpumainos veidos

Drošība

Lietotne nekad nepiesaistās publiski. Noslēpumi paliek .env. Turiet venv un OS ar ielāpiem. Nepalaižiet Gunicorn kā root. Ja apstrādājat pieteikšanos, iestatiet sesijas sīkdatnes Secure un SameSite un konfigurējiet ietvaru uzticēties X-Forwarded-Proto tikai no Nginx. Ierobežojiet pieteikšanās maršrutu ātrumu Nginx vai lietotnē.

  • bind 127.0.0.1 vai unix ligzda
  • chmod 600 .env
  • Neroot User= systemd
  • TLS ar Certbot vai Caddy
  • Izslēdziet atkļūdošanas režīmu un auto-reload ražošanā

Padomi

  • Pievienojiet /health maršrutu, kas pārbauda DB savienojamību Compose un slodzes līdzsvarotājiem
  • Sūtiet statiskos resursus ar cache-control galveni Nginx
  • E-pastam un smagiem darbiem izmantojiet atsevišķu strādnieku vai rindu (Redis + systemd)
  • Piesieniet gunicorn un uvicorn versijas requirements.txt
  • Veiciet momentuzņēmumu pirms pirmās pārejas uz ražošanu

Python lietotne VPS ir gatava ražošanai, kad tā darbojas zem Gunicorn kā systemd pakalpojums, piesaistās tikai localhost un ir sasniedzama caur Nginx vai Caddy ar TLS. Noslēpumus lieciet EnvironmentFile, strādniekus izmēriet pēc RAM, nevis emuāra formulas, un 502 vispirms novērsiet no Gunicorn žurnāla. Kad šis ceļš ir dokumentēts jūsu repo, katra vēlākā izvietošana ir rsync vai git pull, pip install un systemctl restart gunicorn.