Belajar FastAPI - Deployment (Uvicorn/Gunicorn/Docker)
Episode 24 of 28

Belajar FastAPI - Deployment (Uvicorn/Gunicorn/Docker)

Men-deploy aplikasi FastAPI: menjalankan uvicorn multi-worker yang benar, Gunicorn sebagai process manager, multi-stage Dockerfile yang ramping, konfigurasi reverse proxy, hingga deploy ke platform cloud dan Kubernetes.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah 23 episode membangun aplikasi yang lengkap — dari routing sampai AI streaming — sekarang saatnya pergi ke produksi. Episode ini menjawab pertanyaan paling penting di tahap akhir: bagaimana menjalankan FastAPI dengan benar di server, bagaimana mengemasnya ke container, dan di mana men-deploy-nya.

Mengapa episode ini penting? Banyak aplikasi yang bekerja sempurna di laptop gagal di produksi karena hal-hal sederhana: --reload yang aktif, satu worker yang kewalahan, atau image Docker yang bengkak. Episode ini membangun fondasi deployment yang benar sejak langkah pertama.

Uvicorn di Produksi

Ingat episode 3: --reload hanya untuk development. Di produksi, kita butuh banyak worker dan tanpa reload:

Uvicorn multi-worker
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4

Aturan jumlah worker: 2 × jumlah core CPU + 1 (rumus umum untuk I/O-bound). Pada mesin 2-core: --workers 5. Karena workload FastAPI biasanya I/O-bound (menunggu database, HTTP, disk), worker lebih banyak membantu — namun setiap worker memakai memory, jadi sesuaikan dengan RAM yang tersedia.

Warning

Pastikan --reload tidak pernah muncul di produksi — ia memicu restart tanpa sepengetahuan dan menghabiskan resource. Dan --host 0.0.0.0 wajib agar container/server bisa diakses dari luar; 127.0.0.1 hanya untuk development lokal.

Gunicorn sebagai Process Manager

Gunicorn adalah process manager WSGI/ASGI yang lebih matang — dia mengelola worker, restart otomatis saat worker mati, dan sinyal penghentian yang rapi. Pakai Gunicorn sebagai front dan uvicorn worker sebagai engine ASGI:

Install gunicorn
pip install gunicorn
Gunicorn dengan uvicorn worker
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker \
  --bind 0.0.0.0:8000
  • -k uvicorn.workers.UvicornWorker — worker ASGI dari uvicorn.
  • -w 4 — empat worker.
  • Gunicorn mengirim SIGTERM ke worker dan menunggu request selesai saat shutdown — proses restart yang lebih terkontrol.

Tip

Jika aplikasi kalian banyak memakai WebSocket (episode 13), perhatikan bahwa WebSocket diikat ke satu worker — klien tidak boleh pindah worker di tengah koneksi. Di skala besar, pertimbangkan worker-manager atau session affinity di load balancer.

Multi-Stage Dockerfile

Docker mengemas aplikasi + environment menjadi satu artefak yang bisa dideploy di mana saja. Multi-stage memisahkan build dan runtime — hasilnya image ramping:

Dockerfile
FROM python:3.13-slim AS builder
 
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1
 
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
 
FROM python:3.13-slim AS runtime
 
WORKDIR /app
ENV PYTHONPATH=/install
 
COPY --from=builder /install /install
COPY app/ ./app/
 
EXPOSE 8000
CMD ["gunicorn", "app.main:app", "-w", "4", \
     "-k", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000"]

Kenapa multi-stage? Stage builder menginstall dependensi ke /install; stage runtime menyalin hasilnya tanpa lapisan build (compiler, cache pip). Image final berisi hanya yang dibutuhkan untuk menjalankan aplikasi.

Important

Jangan copy .env ke dalam image — secret di image = secret di registry = bocor. Image hanya berisi kode dan dependensi; konfigurasi (episode 16) di-inject saat runtime lewat environment variable. SECRET_KEY dan DATABASE_URL harus hidup di platform, bukan di image.

.dockerignore

Kecilkan build context — file yang tidak perlu ikut ke image:

.dockerignore
.venv/
__pycache__/
*.pyc
.env
uploads/
tests/
.pytest_cache/

Reverse Proxy: Nginx

Aplikasi sebaiknya berada di belakang reverse proxy (Nginx) — proxy menangani TLS, kompresi, dan static files:

nginx.conf
server {
    listen 80;
    server_name api.example.com;
 
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
 
    location /ws/ {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Perhatikan location /ws/: WebSocket butuh header Upgrade khusus — tanpa itu, koneksi WebSocket gagal di balik proxy.

Warning

Setelah memakai reverse proxy, ingat dua hal dari episode 11 dan 19: TrustedHostMiddleware harus berisi server_name yang benar, dan rate limit per-IP butuh ProxyHeadersMiddleware (atau --forwarded-allow-ips) agar IP asli terdeteksi, bukan IP proxy.

Platform Deployment

Image Docker bisa dideploy ke berbagai platform dengan pola yang sama:

PlatformCatatan
Fly.ioContainerized, mudah scale; fly deploy
RenderWeb service dari Docker; auto-deploy dari git
RailwayContainer langsung dari repo; env terpusat
KubernetesSkala penuh: Deployment, Service, Ingress, HPA

Contoh minimal Kubernetes:

deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fastapi-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: fastapi
  template:
    metadata:
      labels:
        app: fastapi
    spec:
      containers:
        - name: app
          image: ghcr.io/kalian/fastapi-app:latest
          ports:
            - containerPort: 8000
          envFrom:
            - secretRef:
                name: app-secrets
          readinessProbe:
            httpGet:
              path: /health
              port: 8000

Tiga hal yang diperhatikan di K8s: replicas untuk skala horizontal, secretRef untuk konfigurasi (episode 16), dan readinessProbe — K8s hanya mengirim trafik ke pod yang health check-nya lolos.

Tip

Endpoint /health itu bukan hiasan — ia dipakai load balancer dan orchestrator untuk memutuskan kapan pod siap menerima trafik. Tambahkan health check di aplikasi kalian sejak awal (topik observability episode 25).

Common Pitfalls

PitfallSolusi
--reload aktif di produksiHapus; gunakan multi-worker
127.0.0.1 di container--host 0.0.0.0
Secret di imageInject via environment
WebSocket gagal di balik proxyHeader Upgrade di Nginx
Image bengkakMulti-stage Dockerfile

Penutup

Inti yang harus dibawa pulang:

  • Produksi: uvicorn --workers 2×core+1 atau Gunicorn + UvicornWorker.
  • Multi-stage Dockerfile: ramping, tanpa secret, gunicorn sebagai CMD.
  • Reverse proxy menangani TLS + WebSocket upgrade; sesuaikan TrustedHost & proxy headers.
  • Deploy di Fly/Render/Railway/K8s; K8s butuh readinessProbe + secret.

Di episode 25 selanjutnya kita akan membahas performance & benchmarking — memprofil endpoint, tuning connection pooling, caching dengan Redis, dan load testing dengan k6. API kalian tidak hanya jalan — sekarang kalian buktikan seberapa cepat ia melaju!

Belajar FastAPI - Deployment (Uvicorn/Gunicorn/Docker) | Belajar FastAPI