Belajar RoadRunner - Docker & Kubernetes Deployment
Episode 21 of 26

Belajar RoadRunner - Docker & Kubernetes Deployment

Men-deploy RoadRunner ke container: membangun image multi-stage dari binary resmi dan PHP, menyusun Docker Compose dengan healthcheck, lalu men-deploy ke Kubernetes dengan Deployment, HPA, dan graceful shutdown memakai SIGTERM.

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

Pendahuluan

Setelah di episode 20 kita menyetel performa, pada episode kali ini kita mengepak semuanya: Docker & Kubernetes. RoadRunner dirancang container-friendly — satu binary + worker PHP dalam satu image, dengan pola shutdown yang bersih untuk orkestrasi modern.

Mengapa episode ini penting? Karena hampir semua production 2026 berjalan di container. Memahami image yang benar, healthcheck yang jujur, dan graceful shutdown adalah syarat agar RoadRunner tidak memutus request saat Kubernetes melakukan rolling update.

Image Multi-Stage

Strategi: stage pertama menyiapkan PHP + dependensi, stage kedua menggabungkannya dengan binary RoadRunner dari image resmi:

Dockerfile - multi-stage
FROM ghcr.io/roadrunner-server/roadrunner:2025.1.15 AS rr
 
FROM php:8.4-cli AS build
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-interaction --prefer-dist \
    && composer dump-autoload --optimize
 
FROM php:8.4-cli
COPY --from=rr /usr/bin/rr /usr/local/bin/rr
COPY --from=build /app/vendor /app/vendor
COPY --from=build /app/composer.json /app/composer.lock /app/
COPY .rr.yaml app.php /app/
 
WORKDIR /app
RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/opcache.ini \
 && echo "opcache.jit=tracing" >> /usr/local/etc/php/conf.d/opcache.ini
 
EXPOSE 8080
CMD ["rr", "serve", "-c", ".rr.yaml"]

Poin penting:

  • Image PHP :cli cukup — tidak butuh FPM, worker dijalankan sebagai proses CLI.
  • Binary rr di-copy dari image resmi roadrunner (versi di-pin).
  • Config opcache ditulis ke file conf — aktif otomatis saat start.
  • CMD menjalankan rr serve sebagai PID 1 — penting untuk sinyal (baca di bawah).

Docker Compose

Untuk development/lokal, susun compose.yaml dengan healthcheck:

compose.yaml
services:
  app:
    build: .
    ports:
      - "8080:8080"
    healthcheck:
      test: ["CMD", "rr", "jobs:list"]
      interval: 10s
      timeout: 5s
      retries: 3
    depends_on:
      redis:
        condition: service_healthy
  redis:
    image: redis:7
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

Healthcheck memakai rr jobs:list — perintah yang ringan dan memvalidasi server + RPC hidup. Alternatif: hit endpoint HTTP /health yang disediakan aplikasi.

Tip

Healthcheck harus memvalidasi kesiapan melayani, bukan sekadar proses hidup. rr jobs:list (atau HTTP GET /health) lebih jujur daripada pgrep rr yang hanya mengecek proses ada.

Kubernetes Deployment

Manifest Kubernetes dengan readiness probe dan resource limit:

Kubernetesdeployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rr-app
  labels:
    app: rr-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: rr-app
  template:
    metadata:
      labels:
        app: rr-app
    spec:
      terminationGracePeriodSeconds: 30
      containers:
        - name: app
          image: registry.example.com/rr-app:2025.1.15
          ports:
            - containerPort: 8080
          envFrom:
            - secretRef:
                name: app-secrets
          resources:
            requests:
              cpu: 250m
              memory: 256Mi
            limits:
              cpu: "1"
              memory: 512Mi
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 3
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health/live
              port: 8080
            periodSeconds: 15

Ditambah Service:

Kubernetesservice.yaml
apiVersion: v1
kind: Service
metadata:
  name: rr-app
spec:
  selector:
    app: rr-app
  ports:
    - port: 80
      targetPort: 8080

Graceful Shutdown (SIGTERM)

Saat Kubernetes menghapus pod (rolling update, scaling down), ia mengirim SIGTERM lalu menunggu terminationGracePeriodSeconds. RoadRunner menangani SIGTERM dengan:

  1. Berhenti menerima request baru.
  2. Menunggu request yang sedang diproses worker selesai.
  3. Mengirim sinyal shutdown ke worker PHP.
  4. Exit dengan kode 0 setelah semua selesai.

Karena itu: jalankan rr sebagai PID 1 (CMD ["rr", ...] tanpa wrapper), dan jangan kirim sinyal lain lebih dulu. Worker PHP juga harus menangani Worker::stop() untuk flush data — pola yang kita bahas di episode 4.

Warning

Jangan pakai kill -9 / force sebagai langkah pertama. Kubernetes memotong terminationGracePeriodSeconds hanya jika SIGTERM tidak selesai tepat waktu. Beri nilai yang cukup (30-60s) untuk aplikasi dengan request yang berjalan lama.

Horizontal Pod Autoscaler

Autoscale berbasis CPU atau metric kustom (episode 12):

Kuberneteshpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: rr-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: rr-app
  minReplicas: 3
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60

Catatan penting: scaling horizontal (replica) berbeda dengan menambah num_workers di dalam satu pod. Mulai dengan replica yang sesuai beban, lalu set num_workers per pod moderat — jangan double-count resource.

Penutup

Pada episode 21 ini, kalian telah men-deploy RoadRunner ke container.

Inti yang harus dibawa pulang:

  • Image multi-stage: PHP CLI + binary rr dari image resmi, versi di-pin.
  • Healthcheck jujur: rr jobs:list atau HTTP /health.
  • Deployment K8s dengan readiness/liveness probe dan resource limit.
  • SIGTERM = graceful shutdown; jangan kill -9 dulu.
  • HPA berbasis CPU untuk autoscale replica.

Di episode 22 selanjutnya, kita belajar cluster, multisite & high availability — memperbanyak replica, session dan queue terdistribusi, strategi zero-downtime deployment, dan menjaga konsistensi antar node. Sampai jumpa di episode 22!

Belajar RoadRunner - Docker & Kubernetes Deployment | Belajar RoadRunner