Claude c1060efd4d
All checks were successful
Helm Chart Release / release-chart (push) Successful in 7s
fix: Auto-install GD extension dependencies
GD拡張が指定された場合、必要な依存パッケージを自動的にインストール。

Changes:
- deployment.yaml: GD拡張検出時に以下を自動追加
  - libpng-dev (PNG処理)
  - libjpeg-turbo-dev (JPEG処理)
  - freetype-dev (フォント処理)
- README.md: GD自動化説明を追加

Usage:
  composer:
    additionalPhpExtensions:
      - "gd"
  # 依存パッケージは自動的にインストール

Benefits:
- ユーザーが手動でadditionalApkPackagesを指定する必要がなし
- インストール失敗の原因を削減
- より簡潔な設定

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-24 10:55:33 +09:00
2026-02-17 01:27:48 +00:00

PHP-FPM Helm Chart

Alpine LinuxベースのNginx + PHP-FPM環境をKubernetesにデプロイするためのHelmチャートです。Composer、Selenium、外部データベース接続など、本格的なPHPアプリケーション実行に必要な機能を統合しています。

特徴

  • 🚀 軽量: Alpine Linuxベースで高速起動
  • 📦 Composer対応: 依存パッケージ管理を柔軟にカスタマイズ
  • 🌐 Nginx統合: PHP-FPMとNginxのマルチコンテナ構成
  • 🔧 カスタマイズ可能: Nginx設定、PHP拡張を自由に追加
  • 🤖 Selenium統合: ブラウザ自動化・スクレイピングに対応
  • 💾 永続化ストレージ: PVCによるデータ永続化
  • 🔐 外部DB接続: MySQL/MariaDB接続機能を内蔵
  • 📊 本番対応: Ingress、TLS、リソース管理に対応

クイックスタート

前提条件

  • Kubernetes 1.19+
  • Helm 3.0+
  • PV プロビジョナーpersistence有効時

基本インストール

# Helmリポジトリを追加
helm repo add cafepieters https://git.cafepieters.com/api/packages/helmchart/helm
helm repo update

# デフォルト設定でインストール
helm install my-phpfpm cafepieters/phpfpm

# カスタム設定でインストール
helm install my-phpfpm cafepieters/phpfpm -f my-values.yaml

# 特定のバージョンをインストール
helm install my-phpfpm cafepieters/phpfpm --version 2.0.0

ソースからのインストール

# リポジトリのクローン
git clone https://git.cafepieters.com/helmchart/phpfpm.git
cd phpfpm

# デフォルト設定でインストール
helm install my-phpfpm .

# カスタム設定でインストール
helm install my-phpfpm . -f my-values.yaml

動作確認

# Podの確認
kubectl get pods -l app.kubernetes.io/name=phpfpm

# サービスの確認
kubectl get svc -l app.kubernetes.io/name=phpfpm

# ログ確認
kubectl logs -l app.kubernetes.io/name=phpfpm -c php-fpm
kubectl logs -l app.kubernetes.io/name=phpfpm -c nginx

アーキテクチャ

┌─────────────────────────────────────────────┐
│  Kubernetes Pod                             │
│                                             │
│  ┌──────────────┐      ┌─────────────────┐ │
│  │   Nginx      │─────▶│   PHP-FPM       │ │
│  │   :80        │      │   :9000         │ │
│  └──────────────┘      │   + Composer    │ │
│         │              │   + Extensions  │ │
│         │              └─────────────────┘ │
│         │                      │           │
│  ┌──────▼──────────────────────▼────────┐  │
│  │   Persistent Volume (PVC)            │  │
│  │   /var/www/html                      │  │
│  └──────────────────────────────────────┘  │
│                                             │
│  ┌─────────────────────────────────────┐   │
│  │   Selenium (Optional)               │   │
│  │   :4444                             │   │
│  └─────────────────────────────────────┘   │
└─────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────┐
│  External Database (Optional)               │
│  MySQL/MariaDB                              │
└─────────────────────────────────────────────┘

主要な設定パラメータ

基本設定

パラメータ 説明 デフォルト
replicaCount Podのレプリカ数 1
image.php.tag PHPバージョン 8.5.2-fpm-alpine3.23
image.nginx.tag Nginxバージョン 1.29.4-alpine-perl
service.type Serviceタイプ LoadBalancer
service.port Serviceポート 80

永続化ストレージ

パラメータ 説明 デフォルト
persistence.enabled PVC有効化 true
persistence.size ストレージサイズ 1Gi
persistence.accessMode アクセスモード ReadWriteOnce

Composer設定

パラメータ 説明 デフォルト
composer.enabled Composer有効化 false
composer.packages インストールパッケージ []
composer.useComposerJson composer.json使用 false
composer.composerJson composer.json内容 ""
composer.installOptions installオプション "--no-dev --optimize-autoloader"
composer.additionalPhpExtensions 追加PHP拡張 []
composer.additionalApkPackages 追加APKパッケージ []

Selenium設定

パラメータ 説明 デフォルト
selenium.enabled Selenium有効化 false
image.selenium.tag Seleniumバージョン 144.0-chromedriver-144.0

外部データベース設定

パラメータ 説明 デフォルト
externalDatabase.enabled 外部DB接続有効化 false
externalDatabase.host DBホスト名 mariadb-hostname
externalDatabase.port DBポート 3306
externalDatabase.database データベース名 dbname
externalDatabase.username ユーザー名 user
externalDatabase.password パスワード pass

SMTP設定

パラメータ 説明 デフォルト
smtp.enabled SMTP機能有効化 false
smtp.host SMTPサーバーホスト名 smtp.example.com
smtp.protocol プロトコルauto/starttls/tls auto
smtp.port ポート番号 587
smtp.auth.enabled 認証有効化 true
smtp.auth.username SMTPユーザー名 smtp-user@example.com
smtp.auth.password SMTPパスワード "" (Secretで指定)
smtp.from 送信元メールアドレス(固定) noreply@example.com
smtp.tls.verify TLS証明書検証 true
smtp.tls.allowSelfSigned 自己署名証明書を許可 false

Ingress設定

パラメータ 説明 デフォルト
ingress.enabled Ingress有効化 false
ingress.className IngressClass名 ""
ingress.annotations アノテーション {}
ingress.hosts ホスト設定 [{host: "example.tld"}]
ingress.tls TLS設定 []

Nginx設定

パラメータ 説明 デフォルト
nginx.customConfig.enabled カスタム設定有効化 false
nginx.customConfig.snippet 設定スニペット ""
nginx.forwardRealIP.enabled リアルIP取得有効化 false
nginx.forwardRealIP.header リアルIP取得ヘッダー "X-Forwarded-For"
nginx.forwardRealIP.recursive 再帰的IP検索 true
nginx.forwardRealIP.trustedProxies 信頼するプロキシネットワーク ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
nginx.forwardRealIP.additionalTrustedProxies 追加の信頼プロキシ []

使用例

例1: シンプルなPHPアプリケーション

# values.yaml
replicaCount: 2

persistence:
  enabled: true
  size: 5Gi

service:
  type: LoadBalancer

resources:
  requests:
    memory: "256Mi"
    cpu: "200m"
  limits:
    memory: "512Mi"
    cpu: "500m"
helm install my-app cafepieters/phpfpm -f values.yaml

例2: Composerパッケージ利用

# values.yaml
composer:
  enabled: true
  packages:
    - "monolog/monolog:^3.0"
    - "guzzlehttp/guzzle:^7.0"
    - "vlucas/phpdotenv:^5.0"
  installOptions: "--no-dev --optimize-autoloader"

persistence:
  enabled: true
  size: 2Gi

例3: composer.jsonを使用

# values.yaml
composer:
  enabled: true
  useComposerJson: true
  composerJson: |
    {
      "require": {
        "php": ">=8.0",
        "slim/slim": "^4.0",
        "slim/psr7": "^1.0",
        "monolog/monolog": "^3.0"
      },
      "autoload": {
        "psr-4": {
          "App\\": "src/"
        }
      }
    }
  installOptions: "--optimize-autoloader"

replicaCount: 3

ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
  hosts:
    - host: api.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: api-tls
      hosts:
        - api.example.com

例4: MySQL接続

# values.yaml
composer:
  enabled: true
  packages:
    - "illuminate/database:^10.0"

externalDatabase:
  enabled: true
  host: mysql.default.svc.cluster.local
  port: 3306
  database: myapp
  username: appuser
  password: "SecurePassword123"

persistence:
  enabled: true
  size: 3Gi

例5: Selenium統合スクレイピング

# values.yaml
composer:
  enabled: true
  packages:
    - "symfony/dom-crawler:^6.0"
    - "symfony/css-selector:^6.0"
    - "monolog/monolog:^3.0"

selenium:
  enabled: true  # php-webdriver/webdriverが自動追加

persistence:
  enabled: true
  size: 5Gi

resources:
  requests:
    memory: "1Gi"
    cpu: "1000m"
  limits:
    memory: "3Gi"
    cpu: "2000m"

PHPコード例:

<?php
require_once '/var/www/html/vendor/autoload.php';

use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;

// Seleniumに接続
$driver = RemoteWebDriver::create(
    'http://localhost:4444',
    DesiredCapabilities::chrome()
);

$driver->get('https://example.com');
echo $driver->getTitle();
$driver->quit();

例6: カスタムNginx設定

# values.yaml
nginx:
  customConfig:
    enabled: true
    snippet: |
      client_max_body_size 100M;
      
      location ~ \.php$ {
          fastcgi_pass 127.0.0.1:9000;
          fastcgi_index index.php;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          include fastcgi_params;
          
          fastcgi_read_timeout 300;
          fastcgi_send_timeout 300;
      }
      
      location /admin {
          auth_basic "Administrator Area";
          auth_basic_user_file /etc/nginx/.htpasswd;
      }

persistence:
  enabled: true

例7: ベアメタル環境でのリアルIP取得

ベアメタルKubernetesやLoadBalancer経由でのアクセスで、PHPからクライアントの実IPアドレスを取得する設定です。

# values.yaml
service:
  type: LoadBalancer

nginx:
  forwardRealIP:
    # リアルIP取得機能を有効化
    enabled: true

    # リアルIPを取得するヘッダー環境に応じて変更
    # - X-Real-IP: シンプルな1段プロキシ
    # - X-Forwarded-For: 多段プロキシ対応(推奨)
    header: "X-Forwarded-For"

    # 再帰的にリアルIPを検索多段プロキシ環境で推奨
    recursive: true

    # 信頼するプロキシのネットワーク範囲
    # ベアメタルクラスターのPodネットワークとServiceネットワークを指定
    trustedProxies:
      - "10.0.0.0/8"      # Kubernetesデフォルトのクラスタネットワーク
      - "172.16.0.0/12"   # Dockerデフォルトネットワーク
      - "192.168.0.0/16"  # プライベートネットワーク

    # 追加で信頼するプロキシ外部LoadBalancerなど
    additionalTrustedProxies:
      - "203.0.113.0/24"  # 外部LoadBalancerのIPレンジ

persistence:
  enabled: true

この設定により、PHP側で以下の変数から実IPアドレスが取得できます

  • $_SERVER['REMOTE_ADDR'] - クライアントの実IPアドレス
  • $_SERVER['HTTP_X_REAL_IP'] - 同上(互換性用)
  • $_SERVER['HTTP_X_FORWARDED_FOR'] - プロキシチェーン全体

検証用PHPコード:

<?php
echo "Real IP: " . $_SERVER['REMOTE_ADDR'] . "\n";
echo "X-Real-IP: " . ($_SERVER['HTTP_X_REAL_IP'] ?? 'not set') . "\n";
echo "X-Forwarded-For: " . ($_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'not set') . "\n";

注意事項:

  • trustedProxiesには、信頼できるプロキシLoadBalancer、Ingressコントローラーのみを指定してください
  • 不正なプロキシを信頼すると、IPスプーフィング攻撃のリスクがあります
  • customConfig.snippetとの併用も可能です(競合しません)

例8: 画像処理アプリケーションGD拡張

# values.yaml
composer:
  enabled: true
  packages:
    - "intervention/image:^2.0"
  additionalPhpExtensions:
    - "gd"
    - "exif"
  # 注GDが指定されている場合、依存パッケージ (libpng-dev, libjpeg-turbo-dev, freetype-dev)
  # は自動的にインストールされます。手動指定は不要です。

persistence:
  enabled: true
  size: 10Gi

service:
  type: ClusterIP

ingress:
  enabled: true
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
  hosts:
    - host: images.example.com

特記事項: GD拡張を additionalPhpExtensions に指定した場合、以下の依存パッケージが自動的にインストールされます:

  • libpng-dev - PNG画像処理
  • libjpeg-turbo-dev - JPEG画像処理
  • freetype-dev - フォント処理

additionalApkPackages で明示的に指定する必要はありません。

例9: 本番環境構成(フル機能)

# production-values.yaml
replicaCount: 5

image:
  php:
    tag: "8.5.2-fpm-alpine3.23"
  nginx:
    tag: "1.29.4-alpine-perl"

composer:
  enabled: true
  useComposerJson: true
  composerJson: |
    {
      "require": {
        "php": ">=8.1",
        "slim/slim": "^4.0",
        "monolog/monolog": "^3.0",
        "vlucas/phpdotenv": "^5.0",
        "firebase/php-jwt": "^6.0"
      },
      "autoload": {
        "psr-4": {
          "App\\": "src/"
        }
      }
    }
  installOptions: "--no-dev --optimize-autoloader --classmap-authoritative"
  additionalPhpExtensions:
    - "opcache"

externalDatabase:
  enabled: true
  host: mysql-primary.database.svc.cluster.local
  port: 3306
  database: production_db
  username: prod_user
  password: "{{ .Values.dbPassword }}"  # 外部から注入

persistence:
  enabled: true
  size: 20Gi
  storageClass: ssd-storage

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  hosts:
    - host: api.production.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: production-tls
      hosts:
        - api.production.com

nginx:
  customConfig:
    enabled: true
    snippet: |
      client_max_body_size 50M;
      fastcgi_read_timeout 300;
      
      # Opcache設定
      fastcgi_param PHP_VALUE "
        opcache.enable=1
        opcache.memory_consumption=256
        opcache.interned_strings_buffer=16
        opcache.max_accelerated_files=10000
        opcache.revalidate_freq=0
        opcache.validate_timestamps=0
      ";

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "1Gi"
    cpu: "1000m"

デプロイ:

# Secretを先に作成
kubectl create secret generic db-password --from-literal=password='SuperSecurePass'

# Helmリポジトリからデプロイ
helm install production-api cafepieters/phpfpm \
  -f production-values.yaml \
  --set externalDatabase.password=$(kubectl get secret db-password -o jsonpath='{.data.password}' | base64 -d)

例10: SMTP設定によるメール送信

PHPアプリケーションからSMTP経由でメール送信を行う設定です。

# values.yaml
smtp:
  enabled: true

  # Gmail の場合
  host: "smtp.gmail.com"
  protocol: "starttls"  # または "tls" (port 465)
  port: 587

  # Office365の場合は以下のようにコメント解除
  # host: "smtp.office365.com"
  # port: 587
  # protocol: "starttls"

  auth:
    enabled: true
    username: "your-email@gmail.com"
    # password は以下の方法で指定:
    # helm install ... --set smtp.auth.password='your-password'
    password: ""

  # 送信元アドレスPHPで上書き可能
  from: "noreply@your-domain.com"

  tls:
    verify: true
    allowSelfSigned: false

persistence:
  enabled: true

PHPでの使用例:

<?php
// 設定を初期化
require_once '/etc/smtp-config/php-smtp-config.php';
SmtpConfig::init();

// デフォルトの送信元で送信
$to = 'user@example.com';
$subject = 'テストメール';
$body = 'このメールはSMTP経由で送信されています。';

if (mail($to, $subject, $body)) {
    echo 'メール送信成功';
} else {
    echo 'メール送信失敗';
}

// 異なる送信元で上書き指定
$headers = [
    'From: custom@your-domain.com',
    'Return-Path: custom@your-domain.com',
];
SmtpConfig::mail($to, $subject, $body, $headers, 'custom@your-domain.com');

デプロイ手順:

# 1. Secretにパスワードを設定して展開
helm install my-app cafepieters/phpfpm \
  -f values.yaml \
  --set smtp.auth.password='your-secure-password'

# または、既存のSecretから取得
helm install my-app cafepieters/phpfpm \
  -f values.yaml \
  --set smtp.auth.password=$(kubectl get secret email-password -o jsonpath='{.data.password}' | base64 -d)

設定詳細:

  • protocol:

    • auto: 自動判定(推奨)
    • starttls: SMTP + STARTTLSポート587
    • tls: SSL/TLSポート465
  • from: 固定の送信元アドレス

    • PHPコードで $fromAddress パラメータを指定することで上書き可能
    • mail($to, $subject, $body, $headers, '-f custom@example.com') で指定
  • 認証: PLAIN認証に対応ほとんどのSMTPサーバーで利用可能

よくある設定:

プロバイダ ホスト ポート プロトコル
Gmail smtp.gmail.com 587 starttls
Office365 smtp.office365.com 587 starttls
Sendgrid smtp.sendgrid.net 587 starttls
Amazon SES email-smtp.region.amazonaws.com 587 starttls

アップグレード

# リポジトリを更新
helm repo update cafepieters

# 最新バージョンにアップグレード
helm upgrade my-phpfpm cafepieters/phpfpm -f values.yaml

# 特定のパラメータのみ変更
helm upgrade my-phpfpm cafepieters/phpfpm --set replicaCount=5

# 特定のバージョンにアップグレード
helm upgrade my-phpfpm cafepieters/phpfpm --version 2.1.0

# ロールバック
helm rollback my-phpfpm 1

アンインストール

# チャートの削除
helm uninstall my-phpfpm

# PVCも削除する場合
kubectl delete pvc -l app.kubernetes.io/name=phpfpm

トラブルシューティング

Pod起動が遅い

原因: Composerパッケージのダウンロード時間

対策:

composer:
  installOptions: "--no-dev --optimize-autoloader --prefer-dist"

メモリ不足エラー

対策:

resources:
  requests:
    memory: "512Mi"
  limits:
    memory: "2Gi"

PHP拡張エラー

対策: 必要なAPKパッケージを追加

composer:
  additionalApkPackages:
    - "build-base"
    - "autoconf"

データベース接続エラー

確認:

# 環境変数確認
kubectl exec -it <pod-name> -c php-fpm -- env | grep DB_

# 接続テスト
kubectl exec -it <pod-name> -c php-fpm -- mysql -h $DB_HOST -u $DB_USER -p$DB_PASS

ログ確認

# PHP-FPMログ
kubectl logs <pod-name> -c php-fpm

# Nginxログ
kubectl logs <pod-name> -c nginx

# Seleniumログ有効時
kubectl logs <pod-name> -c selenium

# リアルタイム監視
kubectl logs -f <pod-name> -c php-fpm

高度な設定

カスタムイメージの使用

image:
  php:
    registry: my-registry.com
    repository: custom-php-fpm
    tag: "latest"

水平オートスケーリング

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

リソース制限の推奨値

環境 CPU Request CPU Limit Memory Request Memory Limit
開発 100m 500m 256Mi 512Mi
ステージング 200m 1000m 512Mi 1Gi
本番(小) 500m 1000m 512Mi 1Gi
本番(大) 1000m 2000m 1Gi 2Gi

セキュリティ考慮事項

データベースパスワードの管理

# Secretの作成
kubectl create secret generic db-secret \
  --from-literal=password='YourSecurePassword'

# values.yamlで参照
externalDatabase:
  password: "{{ .Values.dbPassword }}"

# デプロイ時に注入
helm install my-app . \
  --set dbPassword=$(kubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d)

NetworkPolicyの適用

# networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: phpfpm-netpol
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: phpfpm
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-nginx
    ports:
    - protocol: TCP
      port: 80

パフォーマンス最適化

Opcacheの有効化

composer:
  additionalPhpExtensions:
    - "opcache"

nginx:
  customConfig:
    enabled: true
    snippet: |
      fastcgi_param PHP_VALUE "
        opcache.enable=1
        opcache.memory_consumption=256
        opcache.interned_strings_buffer=16
        opcache.max_accelerated_files=10000
        opcache.revalidate_freq=60
      ";

Composerの最適化

composer:
  installOptions: "--no-dev --optimize-autoloader --classmap-authoritative --apcu-autoloader"
  additionalPhpExtensions:
    - "apcu"
  additionalApkPackages:
    - "apcu-dev"

よくある質問FAQ

Q: Helmリポジトリを追加するには?

A: 以下のコマンドでリポジトリを追加できます。

helm repo add cafepieters https://git.cafepieters.com/api/packages/helmchart/helm
helm repo update

# 利用可能なバージョンを確認
helm search repo cafepieters/phpfpm --versions

Q: PHPバージョンを変更するには?

A: image.php.tagを変更してください。

image:
  php:
    tag: "8.3.15-fpm-alpine3.21"

Q: 複数ドメインに対応できますか?

A: Ingressで複数ホストを設定できます。

ingress:
  hosts:
    - host: domain1.com
      paths: [...]
    - host: domain2.com
      paths: [...]

Q: SeleniumとComposerは同時に使えますか?

A: はい、完全に共存可能です。

Q: 既存のPHPアプリをデプロイするには?

A: PVCにファイルをコピーしてください。

kubectl cp ./my-app <pod-name>:/var/www/html/ -c php-fpm

関連ドキュメント

ライセンス

このHelmチャートはMITライセンスで公開されています。

サポート

変更履歴

v2.0.0

  • Composer対応追加
  • PHP拡張の柔軟な追加機能
  • 統合的な依存関係管理

v1.0.0

  • 初回リリース
  • Nginx + PHP-FPM基本構成
  • Selenium統合
  • 外部データベース対応
Description
PHP-fpm Helm Chart for Kubernetes based on Alpine Linux.
Readme 508 KiB
v8.5.3 Latest
2026-02-16 02:00:40 +00:00
Languages
Smarty 100%