跳轉到

生產部署指南

Docker 部署

Core + Spectrum(基礎映像)

# Dockerfile.nextpdf-core
FROM php:8.5-cli-bookworm

# 安裝 PHP 擴充套件
RUN docker-php-ext-install pcntl
RUN pecl install pcov && docker-php-ext-enable pcov

# 安裝 Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

# 複製應用程式
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-interaction

# 安裝 Spectrum 加速引擎(可選)
COPY --from=ghcr.io/nextpdf-labs/spectrum:latest \
     /usr/local/bin/nextpdf-spectrum \
     /usr/local/bin/nextpdf-spectrum
RUN chmod +x /usr/local/bin/nextpdf-spectrum

COPY . .

CMD ["php", "artisan", "serve", "--host=0.0.0.0"]

Artisan(含 Chrome)

# Dockerfile.nextpdf-artisan
FROM php:8.5-cli-bookworm

# 安裝 Google Chrome
RUN apt-get update && apt-get install -y \
    wget gnupg2 \
    && wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" \
       >> /etc/apt/sources.list.d/google-chrome.list \
    && apt-get update && apt-get install -y google-chrome-stable \
    && rm -rf /var/lib/apt/lists/*

# 建立非 root 使用者
RUN useradd -m -u 1000 nextpdf
USER nextpdf

# ... 其餘步驟

docker-compose(完整堆疊)

# docker-compose.yml
version: '3.9'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.nextpdf-artisan
    environment:
      SPECTRUM_BINARY: /usr/local/bin/nextpdf-spectrum
      GOTENBERG_URL: http://gotenberg:3000
    depends_on:
      gotenberg:
        condition: service_healthy
    volumes:
      - ./fonts:/fonts:ro
      - ./output:/output

  gotenberg:
    image: gotenberg/gotenberg:8
    command:
      - "gotenberg"
      - "--chromium-disable-javascript=true"
      - "--api-timeout=30s"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 10s
      timeout: 5s
      retries: 3
    ports:
      - "3000:3000"

Kubernetes 部署

Deployment 設定

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextpdf-app
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nextpdf-app
  template:
    metadata:
      labels:
        app: nextpdf-app
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
      containers:
        - name: app
          image: ghcr.io/your-org/nextpdf-app:latest
          resources:
            requests:
              memory: "256Mi"
              cpu: "250m"
            limits:
              memory: "1Gi"
              cpu: "1000m"
          env:
            - name: GOTENBERG_URL
              value: "http://gotenberg-service:3000"
            - name: PDF_USER_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: nextpdf-secrets
                  key: pdf-user-password
          volumeMounts:
            - name: fonts
              mountPath: /fonts
              readOnly: true
      volumes:
        - name: fonts
          configMap:
            name: nextpdf-fonts

水平自動擴展

# k8s/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nextpdf-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nextpdf-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

Cloudflare Workers

// wrangler.toml
[vars]
NEXTPDF_FONTS_URL = "https://assets.example.com/fonts"

[[rules]]
type = "ESModule"
globs = ["**/*.mjs"]

環境設定

# .env.production
APP_ENV=production

# NextPDF Core
NEXTPDF_FONT_PATH=/fonts
NEXTPDF_OUTPUT_PATH=/tmp/nextpdf

# Spectrum 加速引擎
SPECTRUM_BINARY=/usr/local/bin/nextpdf-spectrum
SPECTRUM_MAX_CONNECTIONS=4
SPECTRUM_CIRCUIT_BREAKER_THRESHOLD=3

# Gotenberg
GOTENBERG_URL=http://gotenberg:3000
GOTENBERG_TIMEOUT=30

# PDF 加密
PDF_USER_PASSWORD=${SECRET_FROM_VAULT}
PDF_OWNER_PASSWORD=${SECRET_FROM_VAULT}

# SonarQube(CI 用)
SONAR_TOKEN=${SONAR_TOKEN}

安全強化

健康檢查與監控

延伸閱讀