Menjalankan uvicorn main:app --reload di laptop bukan deployment — itu mode pengembangan. Deployment sungguhan menuntut proses yang stabil, dimulai ulang otomatis saat gagal, dan mampu menerima banyak permintaan bersamaan. Pada chapter ini kita membedah anatomi deployment aplikasi web Python dari dalam ke luar, menjalankan server ASGI untuk nyata, lalu membandingkan platform tempat semuanya tinggal.
Anatomi Deployment #
Sebelum sampai ke pengguna, satu permintaan HTTP melewati beberapa lapisan:
Tanggung jawab tiap lapisan berbeda:
- Reverse proxy (nginx, Caddy): menerima koneksi dari internet, menangani TLS/HTTPS, menyajikan berkas statis, dan meneruskan sisanya ke app server.
- App server (uvicorn, gunicorn): menerjemahkan protokol HTTP menjadi pemanggilan objek aplikasi Python — peran WSGI/ASGI yang diperkenalkan pada Chapter Pengenalan WSGI dan ASGI.
- Worker: proses Python yang menjalankan kode aplikasi kita; jumlah lebih dari satu membuat aplikasi memakai banyak core CPU.
Menjalankan uvicorn untuk Nyata #
Mari kita buktikan lapisan tengah bekerja dengan aplikasi FastAPI mini yang memiliki endpoint /healthz:
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/healthz")
def healthz() -> dict[str, str]:
return {"status": "ok"}
@app.get("/")
def root() -> dict[str, str]:
return {"pesan": "Halo dari aplikasi demo"}Jalankan app server pada port tinggi (di luar sesi pengembangan, flag --reload tidak dipakai):
python -m uvicorn main:app --host 127.0.0.1 --port 8123Output yang Dihasilkan:
INFO: Started server process [22564]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8123 (Press CTRL+C to quit)Server hidup. Dari terminal kedua, panggil kedua endpoint:
curl http://127.0.0.1:8123/healthz
curl http://127.0.0.1:8123/Output yang Dihasilkan:
{"status": "ok"}
{"pesan": "Halo dari aplikasi demo"}Log uvicorn kemudian mencatat kedua permintaan tersebut:
INFO: 127.0.0.1:60990 - "GET /healthz HTTP/1.1" 200 OK
INFO: 127.0.0.1:32768 - "GET / HTTP/1.1" 200 OKUntuk aplikasi WSGI klasik (Flask, Django), gunicorn menjadi app server-nya; untuk ASGI, kombinasi gunicorn -k uvicorn.workers.UvicornWorker menambahkan manajemen worker yang teruji ke uvicorn.
Berapa Worker #
Setiap worker adalah proses terpisah dengan interpreter sendiri, jadi jumlahnya mengikuti core CPU — bukan keinginan. Rumus populer dari dokumentasi gunicorn adalah 2 × jumlah core + 1. Server dua core memakai 5 worker; delapan core memakai 17. Aplikasi yang banyak menunggu I/O (database, API eksternal) dapat memakai async ASGI dengan worker lebih sedikit, karena satu worker menangani banyak koneksi sekaligus.
Menjalankan sebagai Service dengan systemd #
Server produksi menuntut aplikasi dinyalakan ulang saat boot dan saat crash. Di VPS Linux, systemd menjawabnya lewat unit file (ilustratif — disusun mengikuti konvensi dokumentasi systemd):
[Unit]
Description=Toko API
After=network.target
[Service]
User=toko
WorkingDirectory=/opt/toko-api
EnvironmentFile=/etc/toko-api/env
ExecStart=/opt/toko-api/.venv/bin/uvicorn toko_api.main:app --host 127.0.0.1 --port 8000 --workers 4
Restart=always
[Install]
WantedBy=multi-user.targetPerhatikan dua keputusan pentingnya: EnvironmentFile memuat konfigurasi tanpa menyimpannya di dalam image (pola chapter sebelumnya), dan Restart=always membangkitkan proses setiap kali mati. Setelah systemctl enable --now toko-api, aplikasi menjadi warga kelas satu di server.
Reverse Proxy #
Lapisan terdepan biasanya nginx atau Caddy. Konfigurasi Caddy termasuk paling ringkas karena sertifikat TLS diterbitkan otomatis:
toko.example.com {
reverse_proxy 127.0.0.1:8000
}Nginx memerlukan beberapa baris lebih banyak (blok location / dengan proxy_pass http://127.0.0.1:8000;), tetapi prinsipnya sama: publik hanya melihat port 443, app server tetap tersembunyi di 127.0.0.1.
Memilih Platform #
| Platform | Contoh | Cocok untuk |
|---|---|---|
| VPS | provider server virtual | kendali penuh, biaya rendah, tim mau mengurus OS |
| Container platform | Fly.io, Render, Railway | image Docker, deploy per push, skala mudah |
| PaaS | platform managed | tanpa sentuh server, fokus kode |
Container platform membaca Dockerfile dari chapter Containerization dengan Docker dan menjalankannya di berbagai wilayah; beberapa di antaranya bahkan mengenal pyproject.toml secara langsung. Pilihan bebas — anatomi lapisannya tetap sama.
Zero-Downtime dan Database di Produksi #
Pengguna tidak boleh melihat halaman error hanya karena kita merilis versi baru. Teknik dasarnya: nyalakan versi baru berdampingan, periksa kesehatannya lewat endpoint /healthz (dibahas pada chapter berikutnya), arahkan reverse proxy ke proses baru, lalu matikan yang lama. Platform modern mengotomatisasi pola ini sebagai rolling deploy. Terakhir, string koneksi database di produksi datang dari environment — DATABASE_URL diisi platform atau secret manager, tidak pernah ditulis di kode — menutup rantai konfigurasi yang kita bangun sejak awal section ini.
Aplikasi sudah melayani pengguna. Pertanyaan berikutnya: bagaimana kita tahu semuanya sehat? Itu pekerjaan monitoring.