26 Commits
Author SHA1 Message Date
GitHub Actions Bot 6ae463fc49 chore: update to PHP 8.5.10, nginx 1.31.5-alpine-perl, selenium 152.0-chromedriver-152.0 2026-09-07 02:00:19 +00:00
claude b872dd4bd9 fix: php-fpmをexec php-fpm -Fで起動しCrashLoopBackOff(9000二重bind)/502を修正
Helm Chart Release / release-chart (push) Successful in 6s
setupシェルの子として起動していたためコンテナ再起動時にシェル(PID1)がSIGTERMを子へ転送せず、旧php-fpmが9000を握ったまま残存し次回起動が Address in use で失敗する自己増殖ループに陥っていた。execでphp-fpmをPID1にしシグナルを直接受けさせ、-Fで必ずフォアグラウンド起動にする。
2026-09-06 19:54:49 +09:00
claude 6de85b9ad4 docs: CLAUDE.md を階層化した共通ルールに合わせて整理し、GEMINI.md と .agents/rules(Antigravity 用参照)を追加
Helm Chart Release / release-chart (push) Successful in 5s
2026-09-04 13:24:02 +09:00
GitHub Actions Bot eb3eef601a chore: update nginx to 1.31.4-alpine-perl, selenium to 151.0-chromedriver-151.0 (no release) 2026-08-24 02:00:21 +00:00
GitHub Actions Bot 7c5e9e44c8 chore: update nginx to 1.31.3-alpine-perl, selenium to 151.0-chromedriver-151.0 (no release) 2026-08-17 02:00:23 +00:00
claudeandClaude Fable 5 e9428c6448 feat: IngressのproxyBodySizeもuploadMaxSizeに自動連動 (v8.5.9-c)
Helm Chart Release / release-chart (push) Successful in 5s
uploadMaxSizeでnginx/PHPのアップロード上限は連動していたが、
ingress.enabled: true の場合、ingress-nginx側にも独自の上限
(デフォルト1MB)があり、そこで先に弾かれるケースが残っていた。

templates/ingress.yaml で、ingress.annotationsに
nginx.ingress.kubernetes.io/proxy-body-sizeが明示指定されていない
場合、uploadMaxSizeの値を自動的に付与するようにした(merge使用、
明示指定があればそちらを優先)。

これでuploadMaxSize 1箇所の設定でnginx・PHP・Ingressの3箇所すべてに
反映される。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 00:09:20 +09:00
claudeandClaude Fable 5 8f1b050bb2 feat: アップロード最大サイズをvalues.yamlで設定可能に (v8.5.9-b)
Helm Chart Release / release-chart (push) Successful in 5s
大きなファイルのアップロードが失敗する問題(nginxとPHPそれぞれに
別々の上限があり、片方だけ上げても失敗する)に対応するため、
uploadMaxSize パラメータを新設(デフォルト 100m)。

- values.yaml: uploadMaxSize を追加
- templates/configmap.yaml: nginx の client_max_body_size に反映
- templates/deployment.yaml: PHP-FPM起動時に
  /usr/local/etc/php/conf.d/99-uploads.ini を生成し、
  upload_max_filesize / post_max_size に同じ値を設定(常時適用)
- README.md: パラメータ表と設計についての注記を追加

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 23:22:26 +09:00
claudeandClaude Fable 5 e27f02992f fix: sitemap.xmlのContent-Typeを application/xml; charset=utf-8 に明示 (v8.5.9-a)
Helm Chart Release / release-chart (push) Successful in 7s
標準のmime.typesでは .xml が text/xml 扱いとなりcharsetが付与されず、
ブラウザやGoogle Search Consoleなどのツールが正しく解釈できない
場合があった。

templates/configmap.yaml のnginx設定に location = /sitemap.xml を
追加し、types {} + default_type で明示的にContent-Typeを指定する
ようにした。静的ファイルの場合のみ有効(PHP動的生成には別途
header()指定が必要)。設定不要・常時有効。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 22:14:31 +09:00
GitHub Actions Bot 1be71b95e4 chore: update to PHP 8.5.9, nginx 1.31.3-alpine-perl, selenium 150.0-chromedriver-150.0 2026-08-03 02:00:23 +00:00
claudeandClaude Fable 5 3d384ab72e feat: Python導入オプションを追加 (v8.5.8-a)
Helm Chart Release / release-chart (push) Successful in 5s
PHPからPythonスクリプトを呼び出す用途向けに、values.yamlの設定
だけでPython仮想環境(venv)を導入できるようにした。既存のComposer
サポートと同じ設計方針(デフォルト導入先はWebルート外・PVC非マウ
ントの使い捨て領域、packages/useRequirementsTxtの二択、
additionalApkPackagesでネイティブ拡張ビルド対応)を踏襲。

- values.yaml: python セクション新設
- templates/deployment.yaml: python3/py3-pipのAPKインストール、
  venv構築、pip install処理を追加(requirements.txtの展開は
  trim | nindent 14 でYAML破壊を回避、v8.5.6-dと同じ手法)
- README.md: パラメータ表・使用例(例12)・注意事項を追加

PHPからは exec('/venv/bin/python3 script.py') で呼び出す。

自動更新ワークフローによりPHP 8.5.8へのフルリリース(v8.5.8)が
先行して行われたため、本機能はそのタグの上に手動リリース 8.5.8-a
として適用する。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 21:23:20 +09:00
GitHub Actions Bot 6e600bb308 chore: update to PHP 8.5.8, nginx 1.31.3-alpine-perl, selenium 150.0-chromedriver-150.0 2026-07-20 02:00:49 +00:00
claudeandClaude Fable 5 4b2dece19b fix: /etc/msmtprc の権限を0600から0644に修正 (v8.5.6-g)
Helm Chart Release / release-chart (push) Successful in 5s
v8.5.6-f でSMTPパスワードファイルの権限は修正したが、
起動スクリプトが chmod 600 していた /etc/msmtprc 自体も
rootのみ読み取り可のままで、PHP-FPMワーカー(www-data等)から
読めず 'msmtp: account default not found' (exit:78) で失敗していた。

chmod 644 に変更。msmtprc には実パスワードは含まれない
(passwordeval経由で別ファイルから取得する設計)ため実害なし。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 07:56:44 +09:00
claudeandClaude Fable 5 ffb760b913 fix: SMTPパスワードSecretのmodeを0600から0644に修正 (v8.5.6-f)
Helm Chart Release / release-chart (push) Successful in 5s
smtp-secrets ボリュームの mode: 0600 により、Secretファイルの所有者は
rootだが、msmtp は PHP mail() 経由で PHP-FPMワーカー(www-data等の
非rootユーザー)として実行されるため読み取れず、
'cat: can't open ... Permission denied' で認証失敗していた。

mode を 0644(全ユーザー読み取り可)に変更。ファイルはPod内にのみ
存在し外部からアクセス不可のため許容できるトレードオフ。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 07:33:28 +09:00
claudeandClaude Fable 5 85b7f69ccb feat: PVCルートを /var/www にマウント、/composer を使い捨て領域に変更 (v8.5.6-e)
Helm Chart Release / release-chart (push) Successful in 6s
php-fpm コンテナのマウントを html サブパスのみから PVCルート
(/var/www)に変更。html/ は公開フォルダ、それ以外は非公開ファイル
の格納先として利用可能に。nginx は従来どおり html サブパスのみ
マウントするため、非公開ディレクトリがWebに公開されることはない。

あわせて /composer のPVC永続化マウントを廃止し、Pod再起動ごとに
クリーン再構築される使い捨て領域とした(マルウェア書き込み対策)。
永続化したい場合は composer.workingDir に /var/www/composer 等を指定。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:03:16 +09:00
claudeandClaude Fable 5 be1c82e968 fix: useComposerJson使用時のYAML parse errorを修正 (v8.5.6-d)
Helm Chart Release / release-chart (push) Successful in 5s
heredoc内の {{ .Values.composer.composerJson }} がインデント無しで
展開され、複数行JSONの2行目以降が行頭に出力されてブロックスカラーを
破壊していた潜在バグを修正。trim | nindent 14 で展開するよう変更
(composerLock も同様)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:31:03 +09:00
claudeandClaude Fable 5 76a4a7874b feat: Composerデフォルト導入先を /composer に変更 (v8.5.6-c)
Helm Chart Release / release-chart (push) Successful in 5s
/var/www はWebルート /var/www/html の親ディレクトリのため、
ネストマウントの副産物としてPVCの composer サブパス内に
空の html/ ディレクトリが生成されていた。

デフォルトの composer.workingDir をWebルートと親子関係にない
/composer に変更してネストマウント自体を解消。

- autoload読み込み: require_once '/composer/vendor/autoload.php';
  (values.yaml のコメントにも明記)
- PVCデータは同じ composer サブパスを使うため移行不要
- 旧Webルートからの自動移行機能(v8.5.6-b)は維持

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:13:51 +09:00
claudeandClaude Fable 5 e294f909c1 fix: 旧Webルートの composer.json を自動移行、mbstring依存を自動追加 (v8.5.6-b)
Helm Chart Release / release-chart (push) Successful in 8s
v8.5.6-a で導入先を /var/www に変更した際、既存の composer.json が
旧Webルート /var/www/html に残っている環境でインストールが
スキップされる問題を修正。起動時に composer.json / composer.lock /
vendor/ を workingDir へ自動移行する。

また additionalPhpExtensions に mbstring 指定時、Alpineでのビルドに
必要な oniguruma-dev を自動追加(configure: error: Package
requirements (oniguruma) were not met 対策)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 14:58:47 +09:00
claudeandClaude Fable 5 8ff43615fa feat: Composer導入先をWebルート外(/var/www)に変更 (v8.5.6-a)
Helm Chart Release / release-chart (push) Successful in 5s
従来はWebルート /var/www/html 直下にComposerを導入していたため、
composer.json / composer.lock / vendor/ がWeb経由で公開され、
依存パッケージ情報の漏洩などのセキュリティリスクがあった。

- values.yaml: composer.workingDir を追加(デフォルト: /var/www)
- templates/deployment.yaml: 作業ディレクトリを workingDir に変更、
  Webルート以外の場合はPVCの composer サブパスをマウントして永続化
- README.md: パラメータ説明・autoload読み込みパスの解説を追加
- Chart.yaml: 8.5.6-a(手動リリース)
- CHANGELOG-8.5.6-a.md: 変更内容を記録

PHP側は require_once '/var/www/vendor/autoload.php'; で読み込む。
旧動作へは composer.workingDir: "/var/www/html" で復帰可能。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 14:29:23 +09:00
GitHub Actions Bot 112fae7059 chore: update nginx to 1.31.1-alpine-perl, selenium to 148.0-chromedriver-148.0 (no release) 2026-05-25 02:00:33 +00:00
GitHub Actions Bot 5aa6583f69 chore: update nginx to 1.31.0-alpine-perl, selenium to 147.0-chromedriver-147.0 (no release) 2026-05-18 02:00:23 +00:00
GitHub Actions Bot 982cc274d8 chore: update to PHP 8.5.6, nginx 1.30.0-alpine-perl, selenium 147.0-chromedriver-147.0 2026-05-11 02:00:26 +00:00
GitHub Actions Bot 3fd01dd7e5 chore: update nginx to 1.30.0-alpine-perl, selenium to 147.0-chromedriver-147.0 (no release) 2026-04-20 02:00:26 +00:00
claudeandClaude Sonnet 4.6 f48879446c feat: phpEnv による汎用 PHP 環境変数サポートを追加
Helm Chart Release / release-chart (push) Successful in 5s
Update Docker Image Tags and Release Helm Chart / update-and-release (push) Successful in 13s
values.yaml の phpEnv マップに設定した任意のキーと値を
PHP-FPM コンテナの環境変数として渡せるようにした。
APIキー・外部サービス設定など DB 接続以外の情報も
同様の方法で PHP に共有できる。

- values.yaml: phpEnv セクション追加
- templates/deployment.yaml: phpEnv を env としてレンダリング
- README.md: パラメータ説明と使用例(例10)を追加
- CLAUDE.md: 新規作成(PHP環境なし・git情報・改修履歴を記録)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 09:58:13 +09:00
GitHub Actions Bot 84ed9e478e chore: update to PHP 8.5.5, nginx 1.29.8-alpine-perl, selenium 147.0-chromedriver-147.0 2026-04-13 02:00:26 +00:00
GitHub Actions Bot c8a745f997 chore: update nginx to 1.29.7-alpine-perl, selenium to 145.0-chromedriver-145.0 (no release) 2026-03-30 02:00:25 +00:00
claudeandClaude Sonnet 4.6 ce6fcab5f3 fix: publish Helm chart to Gitea Package Registry instead of gh-pages
Helm Chart Release / release-chart (push) Successful in 5s
Update Docker Image Tags and Release Helm Chart / update-and-release (push) Successful in 13s
Replace gh-pages branch index approach with direct upload to the
official Gitea Package Registry (same method as helm-release.yaml).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:13:38 +09:00
22 changed files with 1068 additions and 75 deletions
+7
View File
@@ -0,0 +1,7 @@
---
trigger: always_on
description: Read the CLAUDE.md hierarchy via GEMINI.md before doing anything in this workspace
---
最初に、このディレクトリの `GEMINI.md` を読み、そこに列挙された CLAUDE.md を上から順にすべて読んで従うこと。
Read `GEMINI.md` in this directory first, then read and follow every CLAUDE.md it lists, in order.
+15 -45
View File
@@ -5,6 +5,10 @@ on:
- cron: '0 2 * * 1'
workflow_dispatch:
env:
REGISTRY_URL: https://git.cafepieters.com
OWNER: helmchart
jobs:
update-and-release:
runs-on: ubuntu-latest
@@ -222,7 +226,9 @@ jobs:
if: steps.check_update.outputs.php_updated == 'true'
run: |
helm package .
echo "Helm chart packaged"
CHART_FILE=$(ls *.tgz)
echo "CHART_FILE=${CHART_FILE}" >> $GITHUB_ENV
echo "Helm chart packaged: ${CHART_FILE}"
- name: Create Git Tag
if: steps.check_update.outputs.php_updated == 'true'
@@ -258,54 +264,18 @@ jobs:
echo "Release created"
fi
- name: Update Helm Repository Index
- name: Publish to Gitea Package Registry
if: steps.check_update.outputs.php_updated == 'true'
run: |
set -e
APP_VERSION="${{ steps.php.outputs.app_version }}"
CHART_NAME=$(grep '^name:' Chart.yaml | awk '{print $2}')
PACKAGE_FILE="${CHART_NAME}-${APP_VERSION}.tgz"
echo "🚀 Publishing ${CHART_FILE} to Gitea Package Registry..."
echo "Preparing Helm repository update..."
curl --fail-with-body \
-u "${{ secrets.REGISTRY_USER }}:${{ secrets.REGISTRY_TOKEN }}" \
-X POST \
--upload-file "${CHART_FILE}" \
"${REGISTRY_URL}/api/packages/${OWNER}/helm/api/charts"
# パッケージファイルを一時ディレクトリに移動
mkdir -p /tmp/helm-repo
cp "${PACKAGE_FILE}" /tmp/helm-repo/
# gh-pagesブランチの処理
if git ls-remote --heads origin gh-pages | grep gh-pages; then
echo "gh-pages branch exists, checking out..."
git fetch origin gh-pages
git checkout gh-pages
else
echo "Creating new gh-pages branch..."
git checkout --orphan gh-pages
git rm -rf . || true
echo "# Helm Repository" > README.md
git add README.md
git config user.name "GitHub Actions Bot"
git config user.email "actions@github.com"
git commit -m "Initialize gh-pages branch"
git push origin gh-pages
fi
# パッケージファイルをコピー
cp /tmp/helm-repo/"${PACKAGE_FILE}" .
# index.yamlを生成/更新
helm repo index . --url "https://git.cafepieters.com/${GITHUB_REPOSITORY}/raw/branch/gh-pages"
# コミットしてプッシュ
git config user.name "GitHub Actions Bot"
git config user.email "actions@github.com"
git add "${PACKAGE_FILE}" index.yaml
git commit -m "chore: add ${CHART_NAME} v${APP_VERSION}" || echo "No changes to commit"
git push origin gh-pages
echo "Helm repository updated successfully"
# mainブランチに戻る
git checkout main
echo "✅ Chart published successfully!"
- name: Summary
if: steps.check_update.outputs.update_needed == 'true'
+50
View File
@@ -0,0 +1,50 @@
# Changelog - Version 8.5.6-a
## 変更点
### Composer導入先をWebルート外に変更(セキュリティ改善)
従来、Composerは Webルート `/var/www/html` 直下に導入されており、`composer.json` / `composer.lock` / `vendor/` がWeb経由で公開される状態でした。これらのファイルは公開する必要がなく、依存パッケージ構成の漏洩などセキュリティリスクとなるため、デフォルトの導入先をWebルート外の `/var/www` に変更しました。
#### 主な変更点
1. **values.yaml**
- `composer.workingDir` パラメータを追加(デフォルト: `"/var/www"`)
- Composerの導入先ディレクトリを任意のパスに変更可能
2. **templates/deployment.yaml**
- Composer実行時の作業ディレクトリを `composer.workingDir` に変更(`mkdir -p` で自動作成)
- `workingDir` がWebルート(`/var/www/html`)以外の場合、PVCの `composer` サブパスを `workingDir` にマウントし、vendor類を永続化(Pod再起動時の再構築を回避、従来と同等の永続化動作を維持)
3. **README.md**
- `composer.workingDir` のパラメータ説明を追加
- Composer導入先とautoload読み込みパスの解説を追加
- Selenium使用例の `require_once` パスを更新
## PHPコードでの利用
```php
// 新: デフォルトの読み込みパス
require_once '/var/www/vendor/autoload.php';
```
## 互換性
- **注意**: PHPコード内で `require_once '/var/www/html/vendor/autoload.php';` や相対パス `vendor/autoload.php` を使用している場合は、パスの修正が必要です。
- 旧バージョンと同じ動作(Webルート直下に導入)へ戻す場合は、以下を指定してください:
```yaml
composer:
workingDir: "/var/www/html"
```
- 既存のPVC内 `html/vendor` はそのまま残ります。不要であれば手動で削除してください。
## セキュリティ
- `vendor/` や `composer.json` / `composer.lock` がWebサーバー(Nginx)から配信されなくなり、依存パッケージ情報の漏洩や、vendor内スクリプトへの直接アクセスのリスクを排除できます。
---
**リリース日**: 2026-07-19
**担当**: プロサーバーエンジニア(Claude)
+45
View File
@@ -0,0 +1,45 @@
# Changelog - Version 8.5.6-b
## 修正
### 旧Webルートにある既存 composer.json の自動移行
v8.5.6-a で Composer導入先を `/var/www/html` から `/var/www`(`composer.workingDir`)に変更しましたが、
`packages` / `useComposerJson` を使わずに既存の `composer.json` を利用していた環境では、
旧Webルートに残った `composer.json` を検出できず、
「No composer configuration found, skipping package installation」でインストールがスキップされる問題がありました。
**対応**: 起動時に `workingDir` に `composer.json` が無く、旧Webルート `/var/www/html` に存在する場合、
以下のファイルを自動的に `workingDir` へ移行してから `composer install` を実行するようにしました。
- `composer.json`
- `composer.lock`(存在する場合)
- `vendor/`(存在する場合 — 移動によりWebルートから排除され、公開リスクも解消されます)
移行はWebルートから該当ファイルが無くなるため一度だけ実行され、以降の再起動では通常フローで動作します。
### mbstring 拡張の依存パッケージ自動追加
`composer.additionalPhpExtensions` に `mbstring` を指定した場合、
Alpine 上でのビルドに必要な `oniguruma-dev` が無く
`configure: error: Package requirements (oniguruma) were not met` で失敗していました。
**対応**: GD拡張と同様に、`mbstring` 指定時は `oniguruma-dev` を自動的にAPKパッケージへ追加するようにしました。
## アップグレード手順
```bash
helm repo update
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-b -f values.yaml
```
Pod再起動時に自動移行が実行されます。PHPコード側の読み込みパスの更新を忘れずに行ってください:
```php
require_once '/var/www/vendor/autoload.php';
```
---
**リリース日**: 2026-07-19
**担当**: プロサーバーエンジニア(Claude)
+36
View File
@@ -0,0 +1,36 @@
# Changelog - Version 8.5.6-c
## 変更点
### Composerデフォルト導入先を `/var/www` から `/composer` に変更
v8.5.6-a で導入先をWebルート外の `/var/www` に変更しましたが、`/var/www` はWebルート `/var/www/html` の親ディレクトリであるため、ネストマウントの副産物としてPVCの `composer` サブパス内に空の `html/` ディレクトリが生成されていました(マウントポイント作成による正常動作だが紛らわしい)。
**対応**: デフォルトの `composer.workingDir` をWebルートと親子関係にない `/composer` に変更しました。これによりネストマウントが解消され、空フォルダは一切生成されなくなります。
## PHPコードでの利用
```php
require_once '/composer/vendor/autoload.php';
```
※ `values.yaml` のコメントにも読み込み方法を明記しています。
## アップグレード手順
```bash
helm repo update
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-c -f values.yaml
```
## 互換性
- **注意**: v8.5.6-a/b で `/var/www/vendor/autoload.php` を参照するようにPHPコードを更新済みの場合は、`/composer/vendor/autoload.php` への再修正が必要です。
- PVC上のデータは同じ `composer` サブパスを使用するため、既に移行済みの `composer.json` / `vendor/` はそのまま新しいマウント先(`/composer`)に引き継がれます。
- 旧Webルート(`/var/www/html`)からの自動移行機能(v8.5.6-b)はそのまま動作します。
- PVC上に残った空の `composer/html/` ディレクトリは、Pod再起動後は再作成されなくなるため、手動で削除すれば以後復活しません。
---
**リリース日**: 2026-07-19
**担当**: プロサーバーエンジニア(Claude)
+52
View File
@@ -0,0 +1,52 @@
# Changelog - Version 8.5.6-d
## 修正
### useComposerJson 使用時の YAML parse error を修正
`composer.useComposerJson: true` を指定すると、以下のエラーでデプロイに失敗する問題を修正しました。
```
YAML parse error on phpfpm/templates/deployment.yaml:
error converting YAML to JSON: yaml: line 96: did not find expected key.
```
**原因**: `templates/deployment.yaml` の heredoc 内で `{{ .Values.composer.composerJson }}` を
インデント処理なしで展開していたため、複数行の JSON の2行目以降が行頭に出力され、
YAML のブロックスカラー構造を破壊していました(`useComposerJson` 経路の潜在バグ)。
**対応**: `composerJson` / `composerLock` の展開を `trim | nindent 14` に変更し、
ブロックスカラーのインデントに揃えて出力するようにしました。
コンテナ内に書き出される `composer.json` / `composer.lock` は行頭からのクリーンな JSON になります。
## アップグレード手順
```bash
helm repo update
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-d -f values.yaml
```
## 使用例
```yaml
composer:
enabled: true
useComposerJson: true
composerJson: |
{
"require": {
"phpoffice/phpspreadsheet": "^2.0"
}
}
```
PHPコードからの読み込み:
```php
require_once '/composer/vendor/autoload.php';
```
---
**リリース日**: 2026-07-19
**担当**: プロサーバーエンジニア(Claude)
+43
View File
@@ -0,0 +1,43 @@
# Changelog - Version 8.5.6-e
## 変更点
### php-fpm コンテナのマウントを PVCルート → /var/www に変更
従来、php-fpm コンテナには PVC の `html` サブパスのみが `/var/www/html` にマウントされており、PVC上の他のディレクトリにはアクセスできませんでした。
**対応**: php-fpm コンテナには PVC の**ルート**を `/var/www` にマウントするように変更しました。
- `/var/www/html` — 公開フォルダ(nginxが配信するWebルート、従来どおり)
- `/var/www/<任意>` — **非公開ファイルの格納先**(PHPから読み書き可能だがWebには公開されない)
nginx コンテナは従来どおり `html` サブパスのみをマウントするため、`html/` 以外のディレクトリはWebサーバーのファイルシステムに存在せず、公開されることはありません。設定ファイル・秘密鍵・アップロード受け皿など、公開したくないファイルの置き場として利用できます。
### Composer導入先(/composer)を使い捨て領域に変更
v8.5.6-c/d では `/composer` をPVCの `composer` サブパスに永続化していましたが、このマウントを廃止しました。
`/composer` はコンテナローカルの**使い捨て領域**となり、Pod再起動のたびに `composer install` でクリーンに再構築されます。万一不正アクセスで `vendor/` 内にマルウェアを書き込まれても、再起動で消滅します。
- 永続化したい場合は `composer.workingDir` に `/var/www/composer` など `/var/www` 配下を指定してください。
- 再起動ごとにパッケージの再ダウンロードが発生します(クリーン環境維持とのトレードオフ)。
## アップグレード手順
```bash
helm repo update
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-e -f values.yaml
```
## 互換性
- autoloadパスは変わりません: `require_once '/composer/vendor/autoload.php';`
- PVC上に残っている旧 `composer/` サブパスのデータは、今後は `/var/www/composer` として見えます。不要であれば削除してください:
```bash
kubectl exec <pod> -c php-fpm -- rm -rf /var/www/composer
```
---
**リリース日**: 2026-07-19
**担当**: プロサーバーエンジニア(Claude)
+29
View File
@@ -0,0 +1,29 @@
# Changelog - Version 8.5.6-f
## 修正
### SMTPパスワードファイルをPHP-FPMワーカーから読めない問題を修正
`smtp.auth.enabled: true` でSMTP送信メールを設定した際、msmtpが以下のエラーで認証情報を取得できず、メール送信に失敗する問題を修正しました。
```
cat: can't open '/etc/smtp-secrets/password': Permission denied
```
**原因**: `/etc/smtp-secrets/password` を投影するSecretボリュームの `mode` が `0600`(所有者=rootのみ読み取り可)になっていました。msmtp は PHP の `mail()` 呼び出し経由で **PHP-FPMワーカー(`www-data` 等の非rootユーザー)** として実行されるため、rootのみ読み取り可のファイルを読めませんでした。
**対応**: `templates/deployment.yaml` の `smtp-secrets` ボリュームの `mode` を `0644`(全ユーザー読み取り可)に変更しました。このファイルはPod内にのみ存在し外部からアクセスできないため、許容できるトレードオフです。
## アップグレード手順
```bash
helm repo update
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-f -f values.yaml
```
Pod再起動後、SMTP経由のメール送信が正常に動作するようになります。
---
**リリース日**: 2026-07-19
**担当**: プロサーバーエンジニア(Claude)
+46
View File
@@ -0,0 +1,46 @@
# Changelog - Version 8.5.6-g
## 修正
### /etc/msmtprc をPHP-FPMワーカーから読めない問題を修正
v8.5.6-f で `/etc/smtp-secrets/password`(SMTPパスワード)の権限を修正しましたが、
`/etc/msmtprc` 自体にも同様の問題が残っており、以下のエラーでメール送信が失敗していました。
```
ignoring system configuration file /etc/msmtprc: Permission denied
ignoring user configuration file /home/www-data/.msmtprc: No such file or directory
falling back to default account
msmtp: account default not found: no configuration file available
exit:78
```
**原因**: 起動スクリプト(rootで実行)が `/etc/msmtprc` を作成した後、`chmod 600` していたため、
PHP-FPMワーカー(`www-data` 等の非root)から読めませんでした。
**対応**: `templates/deployment.yaml` の `chmod 600 /etc/msmtprc` を `chmod 644` に変更しました。
`msmtprc` には実パスワードは含まれず(`passwordeval` で別ファイルから取得する設計)、
ホスト名・ポート・ユーザー名などの設定のみのため、読み取り権限を広げても実害はありません。
## アップグレード手順
```bash
helm repo update
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-g -f values.yaml
```
Pod再起動後、SMTP経由のメール送信が正常に動作するようになります。
### 動作確認
```bash
kubectl exec -n <namespace> <pod> -c php-fpm -- su -s /bin/sh www-data -c \
'printf "To: test@example.com\r\nFrom: noreply@example.com\r\nSubject: test\r\nMIME-Version: 1.0\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\nbody\r\n" | /usr/bin/msmtp -t --debug; echo "exit:$?"'
```
`exit:0` で成功です。
---
**リリース日**: 2026-07-19
**担当**: プロサーバーエンジニア(Claude)
+58
View File
@@ -0,0 +1,58 @@
# Changelog - Version 8.5.8-a
## 新機能
### Python導入オプションの追加
PHPからPythonスクリプトを呼び出す用途(データ処理・機械学習ライブラリの利用など)向けに、`values.yaml` の設定だけでPython仮想環境(venv)を導入できるようにしました。既存のComposerサポートと同じ設計方針を踏襲しています。
#### 主な変更点
1. **values.yaml**
- `python` セクションを新設
- `enabled`: Python有効化
- `venvDir`: venv導入先(デフォルト `/venv` — Webルート外かつPVCにマウントされない使い捨て領域)
- `packages` / `useRequirementsTxt` / `requirementsTxt`: pipパッケージ指定方法(Composerの `packages` / `useComposerJson` と同じ構造)
- `installOptions`: pip installオプション(デフォルト `--no-cache-dir`)
- `additionalApkPackages`: ネイティブ拡張ビルド用の追加APKパッケージ
2. **templates/deployment.yaml**
- `python.enabled` 時に `python3` / `py3-pip` をAPKでインストール
- `python3 -m venv` で仮想環境を構築
- `useRequirementsTxt` / `packages` に応じてpipインストールを実行
- `requirementsTxt` の複数行内容は `trim | nindent 14` で展開(v8.5.6-d のComposer修正と同じ手法でYAML破壊を回避)
3. **README.md**
- パラメータ表・使用例(例12)を追加
- Alpine(musl)向け事前ビルドwheelが無いパッケージ(numpy等)はビルドに時間がかかる旨の注意書きを追加
## 設計方針(Composerとの一貫性)
- デフォルトの `/venv` はPVCにマウントされず、**Pod再起動のたびにクリーンな環境へ再構築される使い捨て領域**です。不正アクセスで書き込まれても再起動で消えます。
- 永続化したい場合は `python.venvDir` に `/var/www` 配下のパスを指定してください(例: `/var/www/venv`)。
## 使用例
```yaml
python:
enabled: true
useRequirementsTxt: true
requirementsTxt: |
requests>=2.31.0
pandas>=2.0.0
```
PHPからの呼び出し:
```php
exec('/venv/bin/python3 /var/www/scripts/process.py 2>&1', $output, $exitCode);
```
## 互換性
- デフォルトは `enabled: false` のため、既存環境への影響はありません。
---
**リリース日**: 2026-07-19
**担当**: プロサーバーエンジニア(Claude)
+35
View File
@@ -0,0 +1,35 @@
# Changelog - Version 8.5.9-a
## 修正
### sitemap.xml のContent-Typeを明示的に指定
`/sitemap.xml`(静的ファイル)へのアクセス時、標準の `mime.types` では `.xml` が `text/xml` 扱いとなり `charset` が付与されないため、ブラウザやGoogle Search Consoleなどのツールが正しく解釈できない場合がありました。
**対応**: `templates/configmap.yaml` のnginx設定に `location = /sitemap.xml` を追加し、`types { } default_type "application/xml; charset=utf-8";` によって明示的にContent-Typeを指定するようにしました。
```nginx
location = /sitemap.xml {
types { }
default_type "application/xml; charset=utf-8";
try_files $uri =404;
}
```
## 注意事項
- この対応は `/sitemap.xml` が**静的ファイル**として `html/` 直下に配置されている場合に適用されます。
- PHPで動的に生成する場合(`/index.php` へのフォールバック経由)は、nginxのこの設定は適用されません。PHP側で `header('Content-Type: application/xml; charset=utf-8');` を明示的に指定してください。
- 設定不要・常時有効です(values.yamlへの変更はありません)。ファイルが存在しない場合は従来どおり404を返します。
## アップグレード手順
```bash
helm repo update
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-a -f values.yaml
```
---
**リリース日**: 2026-08-06
**担当**: プロサーバーエンジニア(Claude)
+52
View File
@@ -0,0 +1,52 @@
# Changelog - Version 8.5.9-b
## 新機能
### アップロード最大サイズを values.yaml で設定可能に
大きなファイルのアップロードが失敗する問題(nginxとPHPそれぞれに別々のアップロード上限があり、片方だけ上げても失敗する)に対応するため、`uploadMaxSize` パラメータを新設しました。
#### 主な変更点
1. **values.yaml**
- `uploadMaxSize: "100m"` を追加(デフォルト100MB)
2. **templates/configmap.yaml**
- nginx設定に `client_max_body_size {{ .Values.uploadMaxSize }};` を追加
3. **templates/deployment.yaml**
- PHP-FPM起動時に `/usr/local/etc/php/conf.d/99-uploads.ini` を生成し、
`upload_max_filesize` / `post_max_size` に同じ値を設定
- 常時適用(他機能の有効化状態に依存しない)
4. **README.md**
- パラメータ表と、nginx/PHP両方に反映される設計についての注記を追加
## 背景
nginxの `client_max_body_size` だけを上げても、PHPには独自の `upload_max_filesize`(デフォルト2M)/ `post_max_size`(デフォルト8M)という別の上限があり、nginxを通過した後にPHP側で無言で失敗するケースがありました。この2つを同じ値で連動させることで、設定漏れによる失敗を構造的に防ぎます。
## 使用例
```yaml
uploadMaxSize: "100m"
# 大きな動画ファイルなどを扱う場合
# uploadMaxSize: "500m"
```
## 互換性
- デフォルト値は `100m`(従来の暗黙の上限より大幅に緩和)。既存よりアップロード可能サイズが大きくなる方向の変更のため、既存環境への悪影響はありません。
- 大きなファイルをPHP側でメモリに読み込んで処理する場合、`memory_limit`(デフォルト128M程度)が別途不足する可能性がある点に注意してください。
## アップグレード手順
```bash
helm repo update
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-b -f values.yaml
```
---
**リリース日**: 2026-08-06
**担当**: プロサーバーエンジニア(Claude)
+40
View File
@@ -0,0 +1,40 @@
# Changelog - Version 8.5.9-c
## 新機能
### Ingressのアップロードサイズ上限も uploadMaxSize に自動連動
v8.5.9-b で `uploadMaxSize` によりnginx/PHPのアップロード上限を連動させましたが、`ingress.enabled: true` で運用している場合、Ingressコントローラー(ingress-nginx)にも独自のリクエストサイズ上限(デフォルト1MB)があり、そこで先に弾かれてしまうケースが残っていました。
**対応**: `templates/ingress.yaml` で、`ingress.annotations` に `nginx.ingress.kubernetes.io/proxy-body-size` が明示指定されていない場合、`uploadMaxSize` の値を自動的に付与するようにしました。ユーザーが `ingress.annotations` に明示的に指定した場合はそちらが優先されます。
```yaml
# 何も指定しなくても、Ingressにも uploadMaxSize の値(デフォルト100m)が反映される
uploadMaxSize: "100m"
ingress:
enabled: true
```
これにより、`uploadMaxSize` 1箇所の設定で以下すべてに反映されます:
- nginx(Podコンテナ内)の `client_max_body_size`
- PHPの `upload_max_filesize` / `post_max_size`
- ingress-nginxの `nginx.ingress.kubernetes.io/proxy-body-size`
## 互換性
- Ingressコントローラーがingress-nginx以外の場合、このアノテーションは無視されます。該当コントローラー向けの設定を `ingress.annotations` に明示的に指定してください。
- 既存で `ingress.annotations` に独自の `proxy-body-size` を指定している場合、その値がそのまま優先されるため影響ありません。
## アップグレード手順
```bash
helm repo update
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-c -f values.yaml
```
---
**リリース日**: 2026-08-06
**担当**: プロサーバーエンジニア(Claude)
+54
View File
@@ -0,0 +1,54 @@
# Changelog - Version 8.5.9-d
## 不具合修正
### php-fpm を `exec php-fpm -F` で起動(CrashLoopBackOff / 502 の修正)
php-fpm コンテナの起動コマンドを、setup シェルスクリプト末尾の `php-fpm`(シェルの子プロセスとしてフォアグラウンド起動)から **`exec php-fpm -F`** に変更しました。
**背景(実際に発生した障害)**
`selenium.enabled: true` の構成(例: hotels / booking.e-stay.jp)で、php-fpm コンテナが次のエラーで永続的に CrashLoopBackOff に陥る事象が発生しました。
```
[NOTICE] Failed implicitly binding to ::, retrying with 0.0.0.0
[ERROR] unable to bind listening socket for address '9000': Address in use (98)
[ERROR] FPM initialization failed
```
php-fpm が 9000 を bind できず起動に失敗するため、nginx が `fastcgi_pass 127.0.0.1:9000` に投げても FastCGI ではない応答が返り、`upstream sent unsupported FastCGI protocol version: 60` として **全リクエストが 502** になります(`60` = `<`、= 9000 を握っている別プロセスが HTML 等を返している)。
**原因**
起動コマンドが `sh -c "<setup> ... php-fpm"` の形で、**php-fpm が setup シェルの子プロセス**になっていた。コンテナ PID1 はシェルであり、シェルは既定で受け取った `SIGTERM` を子プロセスへ転送しない。そのためコンテナ(php-fpm コンテナのみ)の再起動時に、PID1 のシェルだけが先に終了し、**旧 php-fpm が一時的に残存して 9000 を握ったまま**になることがある。この状態で新しい php-fpm が起動すると `Address in use` で失敗 → 再起動 → 同じ残存 → という自己増殖ループに入り、CrashLoopBackOff から復帰できなくなる。selenium サイドカーは 9000 を使用しておらず無関係(別 pod でのポート占有調査でも確認済み)。
**対応**
- `exec php-fpm` … php-fpm が setup シェルを置き換えて**コンテナの PID1 になる**。kubelet からの `SIGTERM`/`SIGKILL` が php-fpm 本体へ直接届き、停止時に 9000 が確実に解放されるため、次回起動での二重 bind が起きない。
- `-F`(`--nodaemonize`)… php-fpm.conf の `daemonize` 設定に依存せず、必ずフォアグラウンドで起動する(master が背後に残る事故を防ぐ)。
これは全サイト共通で安全な変更(コンテナ内で php-fpm を動かす際の定石)であり、既存の正常稼働サイトの挙動は変わりません。
**復旧手順(重要)**
チャートを `8.5.9-d` に上げても、既存 pod のネットワーク名前空間に残存プロセスがある場合は、その pod を作り直してクリーンな状態にする必要があります。`helm upgrade` で新しい pod に置き換わりますが、置き換わらない場合は crashloop 中の pod を明示的に削除してください。
```bash
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-d -f values.yaml
# 置き換わらない場合:
kubectl delete pod -n <namespace> -l app.kubernetes.io/name=phpfpm
```
**対象ファイル**: `templates/deployment.yaml`, `Chart.yaml`, `README.md`, `CLAUDE.md`, `CHANGELOG-8.5.9-d.md`
## アップグレード手順
```bash
helm repo update
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-d -f values.yaml
```
---
**リリース日**: 2026-09-06
**担当**: プロサーバーエンジニア(Claude)
+120
View File
@@ -0,0 +1,120 @@
# CLAUDE.md — phpfpm Helm Chart
> **共通ルール(要約)** — 詳細は `P:\Claude\CLAUDE.md`(全体共通)と `P:\Claude\HelmChart\CLAUDE.md`(Helm チャート共通: リリースフロー・ワークフロー・Gitea Secrets・クラスタ構成)を参照。
> 作業前に pull / 機能変更時は README 更新 / 作業単位ごとに commit → push まで / コミットに AI クレジットを付けない / pull で入った変更を revert しない / Helm・PHP はローカル実行不可(Python のみ可)。
## リポジトリ概要
Raspberry Pi などのベアメタルで稼働することを想定した、Kubernetes 上で動作する Nginx + PHP-FPM の Helm チャート。
Websites 組織の各サイト(e-learn.jp / fcdomain.com / hotels / tskholding.com など)はこのチャートでデプロイされる。
- **Gitea リポジトリ**: `ssh://git@192.168.9.65/helmchart/phpfpm`
- **Helm リポジトリ**: `https://git.cafepieters.com/api/packages/helmchart/helm`
- **主アプリ**: PHP(`docker.io/php:<tag>-fpm-alpine`)。サブアプリ: nginx
## 実行環境について
**PHP の実行環境(インタープリタ)はこのリポジトリには含まれていない。**
チャートは `docker.io/php:<tag>-fpm-alpine` の公式イメージを Kubernetes 上で起動するものであり、PHP コードそのものは PVC(`/var/www/html`)に別途配置する必要がある。
## 設計上の注意(既知の落とし穴)
- `templates/configmap.yaml` が実際に使われている nginx 設定。`templates/configmap-nginx.yaml` は `.Values.nginx.enabled` が values.yaml に存在せず常に未出力の**死んだファイル**なので注意。
- PVC はルートを `/var/www` にマウントする(`html/` が公開フォルダ、それ以外は非公開)。`/composer` は Pod 再起動ごとにクリーン再構築される使い捨て領域。
- `uploadMaxSize` 1箇所で nginx `client_max_body_size`・PHP `upload_max_filesize`/`post_max_size`・Ingress `proxy-body-size` の3箇所が連動する。
- Secret / ConfigMap をファイルとして PHP-FPM ワーカー(`www-data`)から読ませる場合、権限は `0644` にする(`0600` だと読めない)。
## チャート改修履歴
### php-fpm を `exec php-fpm -F` で起動しCrashLoopBackOffを修正(2026-09-06, v8.5.9-d)
setup シェル末尾の `php-fpm`(シェルの子プロセス)を **`exec php-fpm -F`** に変更。selenium 有効構成(hotels)で php-fpm が `unable to bind ... '9000': Address in use` を出して永続 CrashLoopBackOff になり、nginx が非FastCGI応答を受けて全リクエスト502(`unsupported FastCGI protocol version: 60`)になる障害の修正。原因は php-fpm が setup シェルの子で、コンテナ PID1 のシェルが `SIGTERM` を子へ転送しないため、コンテナ再起動時に旧 php-fpm が残存し 9000 を握ったまま次回起動が二重 bind で失敗する自己増殖ループ。`exec` で php-fpm を PID1 にしてシグナルを直接受けさせ(停止時に 9000 を確実解放)、`-F` で `daemonize` 設定に依存せず必ずフォアグラウンド起動にした。全サイト共通で安全(コンテナで php-fpm を動かす定石)。復旧には `helm upgrade` に加え、残存プロセスを持つ既存 pod の削除が必要な場合がある。
**対象ファイル**: `templates/deployment.yaml`, `Chart.yaml`, `README.md`, `CLAUDE.md`, `CHANGELOG-8.5.9-d.md`
### Ingressのproxy-body-sizeもuploadMaxSizeに連動(2026-08-06, v8.5.9-c)
v8.5.9-bのフォローアップ。`templates/ingress.yaml` で `merge (deepCopy .Values.ingress.annotations) (dict "nginx.ingress.kubernetes.io/proxy-body-size" .Values.uploadMaxSize)` を使い、ユーザーが明示指定していなければ `uploadMaxSize` をIngressの `proxy-body-size` にも自動反映。明示指定があればそちらが優先(sprigのmergeはdst=ユーザー指定annotationsが優先、srcのデフォルト値は不足分のみ補う)。これで `uploadMaxSize` 1箇所でnginx・PHP・Ingressの3箇所すべてが揃う。
**対象ファイル**: `templates/ingress.yaml`, `values.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.9-c.md`
### uploadMaxSize の追加(2026-08-06, v8.5.9-b)
nginxの `client_max_body_size` とPHPの `upload_max_filesize`/`post_max_size` を1つの `uploadMaxSize`(デフォルト `"100m"`)で連動させるパラメータを追加。片方だけ上げてももう片方の上限でアップロードが無言で失敗する問題への対応。PHP側は起動時に `/usr/local/etc/php/conf.d/99-uploads.ini` を常時生成(他機能の有効/無効に依存しない)。memory_limitは対象外(別途必要なら将来検討)。
**対象ファイル**: `values.yaml`, `templates/configmap.yaml`, `templates/deployment.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.9-b.md`
### sitemap.xml のContent-Type明示(2026-08-06, v8.5.9-a)
`templates/configmap.yaml` に `location = /sitemap.xml { types { } default_type "application/xml; charset=utf-8"; ... }` を追加。標準mime.typesでは `.xml` が `text/xml` 扱いでcharset無しになる問題への対応。静的ファイルの場合のみ有効、PHP動的生成には効かない(PHP側でheader()指定が必要)。設定不要・常時有効。
**対象ファイル**: `templates/configmap.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.9-a.md`
### Python導入オプションの追加(2026-07-19, v8.5.8-a)
`python` セクションを新設し、`values.yaml` の設定だけでPython仮想環境(venv)を導入可能にした。Composerと同じ設計方針(デフォルト導入先 `/venv` はPVC非マウントの使い捨て領域、`packages`/`useRequirementsTxt`の二択、`additionalApkPackages`でネイティブ拡張ビルド対応)。requirements.txtの展開は `trim | nindent 14`(v8.5.6-dのバグ修正と同じ手法)。PHPからは `exec('/venv/bin/python3 script.py')` で呼び出す。
なお、この改修中に自動更新ワークフローがPHP 8.5.8へのフルリリース(v8.5.8)を実行したため、本機能はそのタグの上に手動リリース `8.5.8-a` として適用した。
**対象ファイル**: `values.yaml`, `templates/deployment.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.8-a.md`
### /etc/msmtprc の権限を0600→0644に修正(2026-07-19, v8.5.6-g)
v8.5.6-f のフォローアップ。`/etc/smtp-secrets/password` の権限修正だけでは不十分で、起動スクリプトが `cp` 後に `chmod 600` していた `/etc/msmtprc` 自体もrootのみ読み取り可のままだった(msmtp: account default not found, exit:78)。`chmod 644` に変更。msmtprcには平文パスワードは含まれない(passwordeval経由で別ファイル参照)ため実害なし。
**対象ファイル**: `templates/deployment.yaml`, `Chart.yaml`, `CHANGELOG-8.5.6-g.md`
### SMTPパスワードSecretの権限を0600→0644に修正(2026-07-19, v8.5.6-f)
`smtp-secrets` ボリュームの `mode: 0600` が原因で、rootではなく `www-data`(PHP-FPMワーカー)として動く msmtp が `/etc/smtp-secrets/password` を読めず、SMTP認証に失敗する不具合を修正。`0644` に変更(Pod内にしか存在しないファイルのため許容範囲)。
**対象ファイル**: `templates/deployment.yaml`, `Chart.yaml`, `CHANGELOG-8.5.6-f.md`
### PVCルートを /var/www にマウント + /composer を使い捨て化(2026-07-19, v8.5.6-e)
php-fpm コンテナのマウントを「`html` サブパスのみ」から「PVCルート → `/var/www`」に変更。`html/` は公開フォルダ、それ以外(`/var/www/<任意>`)は非公開ファイルの格納先として使える。nginx は `html` サブパスのみマウントするため非公開分は公開されない。あわせて `/composer` のPVC永続化マウントを廃止し、Pod再起動ごとにクリーン再構築される使い捨て領域とした(マルウェア混入対策、ユーザー要望)。永続化したい場合は `workingDir` に `/var/www/composer` 等を指定。
**対象ファイル**: `templates/deployment.yaml`, `values.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.6-e.md`
### useComposerJson の YAML parse error 修正(2026-07-19, v8.5.6-d)
`useComposerJson: true` 指定時、heredoc 内の `{{ .Values.composer.composerJson }}` がインデント無しで展開され、複数行JSONの2行目以降がブロックスカラーを破壊して YAML parse error になる潜在バグを修正。`trim | nindent 14` で展開するよう変更(`composerLock` も同様)。
**対象ファイル**: `templates/deployment.yaml`, `Chart.yaml`, `CHANGELOG-8.5.6-d.md`
### Composerデフォルト導入先を /composer に変更(2026-07-19, v8.5.6-c)
`/var/www` はWebルート `/var/www/html` の親のため、ネストマウントでPVCの `composer` サブパス内に空の `html/` が生成されていた。デフォルトをWebルートと親子関係にない `/composer` に変更してネストを解消。autoloadは `require_once '/composer/vendor/autoload.php';`(values.yaml のコメントにも明記)。
**対象ファイル**: `values.yaml`, `templates/deployment.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.6-c.md`
### 旧composer.jsonの自動移行 + mbstring依存の自動追加(2026-07-19, v8.5.6-b)
v8.5.6-a のフォローアップ。起動時に `workingDir` に `composer.json` が無く旧Webルート `/var/www/html` にある場合、`composer.json` / `composer.lock` / `vendor/` を自動移行する。また `additionalPhpExtensions` に `mbstring` 指定時、ビルドに必要な `oniguruma-dev` を自動追加(GDと同じ仕組み)。
なお、PVC上の `composer/html/`(空ディレクトリ)はネストマウントのマウントポイント作成による正常な副産物で、実害なし。
**対象ファイル**: `templates/deployment.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.6-b.md`
### composer.workingDir — Composer導入先のWebルート外への変更(2026-07-19, v8.5.6-a)
Composerの導入先をWebルート `/var/www/html` からWebルート外の `/var/www` に変更し、`vendor/` や `composer.json` がWeb経由で公開されないようにした。`values.yaml` の `composer.workingDir` で導入先を変更可能(旧動作に戻すには `"/var/www/html"` を指定)。導入先がWebルート以外の場合、PVCの `composer` サブパスをマウントして永続化する。
PHP側の読み込みは `require_once '/var/www/vendor/autoload.php';`。
**対象ファイル**: `values.yaml`, `templates/deployment.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.6-a.md`
### phpEnv — 汎用 PHP 環境変数サポート(2026-04-17)
`values.yaml` に `phpEnv` セクションを追加し、DB 接続情報と同様に任意のキーと値を PHP-FPM コンテナの環境変数として渡せるようにした。
```yaml
phpEnv:
API_KEY: "your-api-key"
STRIPE_SECRET: "sk_live_..."
REDIS_URL: "redis://localhost:6379"
```
PHP 側では `$_ENV['API_KEY']` または `getenv('API_KEY')` で取得できる。
**対象ファイル**: `values.yaml`, `templates/deployment.yaml`, `README.md`
+2 -2
View File
@@ -2,6 +2,6 @@ apiVersion: v2
name: phpfpm
description: Nginx + PHP-FPM Helm Chart with external DB and optional Selenium support
type: application
version: 8.5.4
appVersion: "8.5.4"
version: 8.5.10
appVersion: "8.5.10"
icon: https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/PHP-logo.svg/330px-PHP-logo.svg.png
+24
View File
@@ -0,0 +1,24 @@
# GEMINI.md — Antigravity (Gemini) 用エントリポイント(HelmChart\phpfpm)
このディレクトリのルールはすべて **`CLAUDE.md`** に記載されている。本ファイルにはルール本文を書かず、読むべき CLAUDE.md への参照だけを置く(正本は常に CLAUDE.md)。
## 必ず最初に実行すること
以下のファイルを**上から順に**読み込み、すべての指示に従うこと。上位ほど広い範囲に適用される共通ルールで、下位は上位を前提とした補足・例外である。
1. `P:\Claude\CLAUDE.md` — 全組織共通ルール(Git 運用・コミット書式・実行環境・情報記載の原則)
2. `P:\Claude\HelmChart\CLAUDE.md` — HelmChart 組織共通ルール
3. `P:\Claude\HelmChart\phpfpm\CLAUDE.md` — phpfpm リポジトリ固有ルール(このディレクトリ)
> Antigravity はワークスペース(または git ルート)直下のルールしか自動で読まず、親フォルダを遡らない。そのため上位階層のパスをここに明示している。`P:\Claude` はクラウド同期されており、デスクトップ・ノート PC とも同じパスで存在する。
## 読み替え
- CLAUDE.md 中の「Claude」「Claude Code」は、Antigravity で作業する場合は Gemini 自身のことと読み替える。
- Git のコミット者は Antigravity でも `user.name = Claude` / `user.email = claude@cafepieters.com` のまま使う(変更しない)。コミットメッセージに AI クレジットを付けない。
- Claude Code 固有の機能(`.claude/` 設定、スキル、メモリ等)に関する記述は無視してよい。
## 保守ルール
- ルールの追加・変更は **CLAUDE.md にのみ**行う。本ファイルと `.agents/rules/claude-md.md` は参照だけを保持し、内容を増やさない。
- CLAUDE.md を新しいディレクトリに追加したときは、同じ形式の `GEMINI.md` と `.agents/rules/claude-md.md` も併置する。
+161 -2
View File
@@ -108,6 +108,17 @@ kubectl logs -l app.kubernetes.io/name=phpfpm -c nginx
| `image.nginx.tag` | Nginxバージョン | `1.29.4-alpine-perl` |
| `service.type` | Serviceタイプ | `LoadBalancer` |
| `service.port` | Serviceポート | `80` |
| `uploadMaxSize` | アップロード最大サイズ(nginx/PHP両方に反映) | `"100m"` |
> **📌 アップロードサイズ上限について**
> `uploadMaxSize` の値は、以下**すべて**に同時に反映されます。どれか一つでも小さいと、そこで上限に達して失敗するため、この1つの値で揃える設計です。
> - nginx(Podコンテナ内)の `client_max_body_size`
> - PHPの `upload_max_filesize` / `post_max_size`
> - `ingress.enabled: true` の場合、ingress-nginxの `nginx.ingress.kubernetes.io/proxy-body-size`(明示指定があればそちらが優先)
>
> 単位は `k` / `m` / `g`(大文字小文字問わず)が使用できます(例: `"200m"`, `"1g"`)。
>
> 大きなファイルをPHP側でメモリに読み込んで処理する場合は、PHPの `memory_limit`(デフォルト128M程度)が不足する可能性があります。その場合は `phpEnv` 等ではなくカスタムイメージ、または将来的な設定拡張で対応してください。
### 永続化ストレージ
@@ -117,11 +128,20 @@ kubectl logs -l app.kubernetes.io/name=phpfpm -c nginx
| `persistence.size` | ストレージサイズ | `1Gi` |
| `persistence.accessMode` | アクセスモード | `ReadWriteOnce` |
> **📁 PVCマウント構成(php-fpmコンテナ)**
> php-fpm コンテナには PVC の**ルート**が `/var/www` にマウントされます。
>
> - `/var/www/html` — **公開フォルダ**(nginxが配信するWebルート)
> - `/var/www/<任意のフォルダ>` — **非公開の格納先**(PHPからは読み書きできるが、Web経由では公開されない)
>
> nginx コンテナは `html` サブパスのみをマウントするため、`html/` 以外のディレクトリはWebサーバーのファイルシステムに存在せず、設定ミスでも公開されることはありません。設定ファイル・秘密鍵・アップロード受け皿・ログなど、公開したくないファイルの置き場として利用できます。
### Composer設定
| パラメータ | 説明 | デフォルト |
|-----------|------|-----------|
| `composer.enabled` | Composer有効化 | `false` |
| `composer.workingDir` | Composer導入先ディレクトリ(`{workingDir}/vendor/autoload.php`) | `"/composer"` |
| `composer.packages` | インストールパッケージ | `[]` |
| `composer.useComposerJson` | composer.json使用 | `false` |
| `composer.composerJson` | composer.json内容 | `""` |
@@ -129,6 +149,30 @@ kubectl logs -l app.kubernetes.io/name=phpfpm -c nginx
| `composer.additionalPhpExtensions` | 追加PHP拡張 | `[]` |
| `composer.additionalApkPackages` | 追加APKパッケージ | `[]` |
### Python設定(オプション)
PHPからPythonスクリプトを呼び出す用途(データ処理・機械学習ライブラリの利用など)向けに、Python仮想環境(venv)を導入できます。
| パラメータ | 説明 | デフォルト |
|-----------|------|-----------|
| `python.enabled` | Python有効化 | `false` |
| `python.venvDir` | venv導入先ディレクトリ(`{venvDir}/bin/python3`) | `"/venv"` |
| `python.packages` | pipでインストールするパッケージ | `[]` |
| `python.useRequirementsTxt` | requirements.txt使用 | `false` |
| `python.requirementsTxt` | requirements.txtの内容 | `"requests>=2.31.0"` |
| `python.installOptions` | pip installオプション | `"--no-cache-dir"` |
| `python.additionalApkPackages` | 追加APKパッケージ(ネイティブ拡張のビルド用) | `[]` |
> **📌 Python導入先について**
> Composerと同様、デフォルトの `/venv` は**Webルート外かつPVCにマウントされない使い捨て領域**です。Pod再起動のたびにクリーンな仮想環境へ再構築されます。PVCに永続化したい場合は `python.venvDir` に `/var/www` 配下(例: `/var/www/venv`)を指定してください。
>
> PHPコードからは `exec()` 等で呼び出します:
> ```php
> exec('/venv/bin/python3 /var/www/scripts/process.py 2>&1', $output, $exitCode);
> ```
>
> **⚠️ 注意**: `numpy` や `pillow` など、Alpine(musl)向けの事前ビルド済みwheelが無いパッケージは、Pod起動のたびにソースからビルドされ、Raspberry Pi等のARM環境では起動に数分〜十数分かかる場合があります。ビルドに必要なパッケージ(`gcc`, `musl-dev`, `python3-dev` 等)は `python.additionalApkPackages` に指定してください。永続化(`venvDir`をPVC配下に)すれば再起動のたびの再ビルドを回避できますが、使い捨てによるクリーン環境維持のメリットとのトレードオフになります。
### Selenium設定
| パラメータ | 説明 | デフォルト |
@@ -147,6 +191,14 @@ kubectl logs -l app.kubernetes.io/name=phpfpm -c nginx
| `externalDatabase.username` | ユーザー名 | `user` |
| `externalDatabase.password` | パスワード | `pass` |
### PHP 汎用環境変数(phpEnv)
| パラメータ | 説明 | デフォルト |
|-----------|------|-----------|
| `phpEnv` | PHP-FPM コンテナに渡す任意の環境変数(キーと値のマップ) | `{}` |
PHP 側では `$_ENV['KEY']` または `getenv('KEY')` で取得できます。
### SMTP設定
| パラメータ | 説明 | デフォルト |
@@ -172,6 +224,9 @@ kubectl logs -l app.kubernetes.io/name=phpfpm -c nginx
| `ingress.hosts` | ホスト設定 | `[{host: "example.tld"}]` |
| `ingress.tls` | TLS設定 | `[]` |
> **📌 Ingressのアップロードサイズ上限**
> `ingress.enabled: true` の場合、`nginx.ingress.kubernetes.io/proxy-body-size` アノテーションが `uploadMaxSize` の値で**自動的に**付与されます(明示的に `ingress.annotations` へ指定した場合はそちらが優先されます)。Ingressコントローラーがnginx以外の場合は、`ingress.annotations` にそのコントローラー向けの上限設定を明示的に指定してください。
### Nginx設定
| パラメータ | 説明 | デフォルト |
@@ -184,6 +239,10 @@ kubectl logs -l app.kubernetes.io/name=phpfpm -c nginx
| `nginx.forwardRealIP.trustedProxies` | 信頼するプロキシネットワーク | `["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]` |
| `nginx.forwardRealIP.additionalTrustedProxies` | 追加の信頼プロキシ | `[]` |
> **📌 sitemap.xml のContent-Type**
> `/sitemap.xml`(静的ファイルとして配置した場合)は、常に `Content-Type: application/xml; charset=utf-8` で配信されます。標準の `mime.types` では `.xml` が `text/xml` 扱いでcharsetが付かず、ブラウザやGoogle Search Consoleなどのツールが正しく解釈できない場合があるための組み込み対応です(設定不要、常時有効)。
> なお、PHPで動的に生成する場合はこの設定は適用されません(PHP側で `header('Content-Type: application/xml; charset=utf-8');` を指定してください)。
## 使用例
### 例1: シンプルなPHPアプリケーション
@@ -229,6 +288,21 @@ persistence:
size: 2Gi
```
> **📌 Composerの導入先について**
> Composerパッケージはデフォルトで**Webルート外**の `/composer` に導入されます(`composer.workingDir` で変更可能)。
> `vendor/` や `composer.json` がWeb経由で公開されないため、情報漏洩などのセキュリティリスクを回避できます。
>
> `/composer` は**PVCにマウントされない使い捨て領域**です。Pod再起動のたびにクリーンな環境へ再構築されるため、万一不正アクセスでマルウェアを書き込まれても再起動で消え、常にクリーンなComposer環境を維持できます(PVCに永続化したい場合は `/var/www/composer` など `/var/www` 配下を指定)。
>
> PHPコードからは以下のように読み込みます:
> ```php
> require_once '/composer/vendor/autoload.php';
> ```
>
> 旧バージョン(Webルート直下 `/var/www/html` に導入)と同じ動作に戻す場合は `composer.workingDir: "/var/www/html"` を指定してください。
>
> **旧バージョンからのアップグレード**: 旧Webルートに `composer.json` / `composer.lock` / `vendor/` が残っている場合、Pod起動時に自動的に `workingDir` へ移行されます(v8.5.6-b以降)。
### 例3: composer.jsonを使用
```yaml
@@ -322,7 +396,7 @@ resources:
**PHPコード例**:
```php
<?php
require_once '/var/www/html/vendor/autoload.php';
require_once '/composer/vendor/autoload.php';
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
@@ -564,7 +638,43 @@ helm install production-api cafepieters/phpfpm \
--set externalDatabase.password=$(kubectl get secret db-password -o jsonpath='{.data.password}' | base64 -d)
```
### 例10: SMTP設定によるメール送信
### 例10: APIキーなどの任意環境変数を PHP に渡す(phpEnv)
`phpEnv` を使うと、DB 接続情報と同様に任意のキーと値を PHP-FPM コンテナの環境変数として渡せます。
```yaml
# values.yaml
phpEnv:
API_KEY: "your-api-key"
STRIPE_SECRET: "sk_live_xxxxxxxxxxxxxxxx"
REDIS_URL: "redis://localhost:6379"
EXTERNAL_SERVICE_URL: "https://api.example.com"
```
**PHPでの使用例**:
```php
<?php
// $_ENV または getenv() で取得
$apiKey = getenv('API_KEY');
$stripe = $_ENV['STRIPE_SECRET'];
$redisUrl = getenv('REDIS_URL');
echo "API Key: " . $apiKey;
```
**確認コマンド**:
```bash
# 設定された環境変数を確認
kubectl exec -it <pod-name> -c php-fpm -- env | grep -E "API_|STRIPE_|REDIS_"
```
**注意事項**:
- 機密性の高い値(APIキー、シークレット等)は `--set phpEnv.KEY=value` でデプロイ時に注入するか、Kubernetes の Secret を別途作成して参照することを推奨します。
- `phpEnv` の値はすべてプレーンテキストとして環境変数に設定されます(externalDatabase の password のみ Secret 経由)。
### 例11: SMTP設定によるメール送信
PHPアプリケーションからSMTP経由でメール送信を行う設定です。
@@ -628,6 +738,37 @@ $headers = [
SmtpConfig::mail($to, $subject, $body, $headers, 'custom@your-domain.com');
```
### 例12: Python連携(requirements.txtを使用)
PHPからPythonスクリプトを呼び出してデータ処理を行う設定です。
```yaml
# values.yaml
python:
enabled: true
useRequirementsTxt: true
requirementsTxt: |
requests>=2.31.0
pandas>=2.0.0
installOptions: "--no-cache-dir"
```
**PHPでの使用例**:
```php
<?php
$script = escapeshellarg('/var/www/scripts/process.py');
exec("/venv/bin/python3 {$script} 2>&1", $output, $exitCode);
if ($exitCode === 0) {
echo implode("\n", $output);
} else {
error_log('Python script failed: ' . implode("\n", $output));
}
```
`/var/www/scripts/` のようなPVC上の非公開フォルダにPythonスクリプトを配置すれば、Web経由で公開されずに済みます(詳細はPVCマウント構成の項を参照)。
**デプロイ手順**:
```bash
@@ -726,6 +867,24 @@ composer:
- "autoconf"
```
### php-fpm が CrashLoopBackOff/全リクエストが 502(`Address in use` / `unsupported FastCGI protocol version: 60`)
**症状**: php-fpm コンテナが `CrashLoopBackOff` になり、nginx ログに `upstream sent unsupported FastCGI protocol version: 60`、php-fpm ログに次が出る。
```
[ERROR] unable to bind listening socket for address '9000': Address in use (98)
[ERROR] FPM initialization failed
```
**原因**: php-fpm が 9000 を bind できず起動失敗し、nginx が非 FastCGI 応答を受けて 502 になる。v8.5.9-c 以前は php-fpm を setup シェルの子プロセスとして起動していたため、コンテナ再起動時に PID1 のシェルが `SIGTERM` を子へ転送せず、旧 php-fpm が残存して 9000 を握ったまま次回起動が二重 bind で失敗する自己増殖ループに陥ることがあった。
**対策**: **v8.5.9-d 以降にアップグレードする**(起動を `exec php-fpm -F` に変更済み。php-fpm が PID1 になりシグナルを直接受けて 9000 を確実解放、`-F` で必ずフォアグラウンド起動)。アップグレード後も残存プロセスを持つ既存 pod が残る場合は作り直す。
```bash
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-d -f values.yaml
kubectl delete pod -n <namespace> -l app.kubernetes.io/name=phpfpm
```
### データベース接続エラー
**確認**:
+12
View File
@@ -55,6 +55,18 @@ data:
root /var/www/html;
index index.php index.html index.htm;
# アップロード可能な最大サイズ(PHP側のupload_max_filesize/post_max_sizeと連動)
client_max_body_size {{ .Values.uploadMaxSize }};
# sitemap.xml のContent-Typeを明示的に指定
# 標準のmime.typesでは .xml は text/xml 扱いでcharsetが付かず、
# ブラウザやSearch Consoleが正しく解釈できない場合があるため
location = /sitemap.xml {
types { }
default_type "application/xml; charset=utf-8";
try_files $uri =404;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
+101 -12
View File
@@ -36,7 +36,15 @@ spec:
- |
echo "Starting PHP-FPM setup process..."
{{- if or .Values.composer.enabled .Values.selenium.enabled .Values.externalDatabase.enabled }}
# ========================================
# アップロードサイズ上限(nginxのclient_max_body_sizeと連動)
# ========================================
cat > /usr/local/etc/php/conf.d/99-uploads.ini << 'UPLOADS_INI_EOF'
upload_max_filesize = {{ .Values.uploadMaxSize }}
post_max_size = {{ .Values.uploadMaxSize }}
UPLOADS_INI_EOF
{{- if or .Values.composer.enabled .Values.selenium.enabled .Values.externalDatabase.enabled .Values.python.enabled }}
# ========================================
# APKパッケージのインストール
# ========================================
@@ -57,20 +65,35 @@ spec:
APK_PACKAGES="$APK_PACKAGES msmtp ca-certificates"
{{- end }}
{{- if .Values.python.enabled }}
# Python本体に必要なパッケージ
APK_PACKAGES="$APK_PACKAGES python3 py3-pip"
{{- end }}
{{- if .Values.composer.additionalApkPackages }}
# ユーザー指定の追加APKパッケージ
# ユーザー指定の追加APKパッケージ(Composer用)
{{- range .Values.composer.additionalApkPackages }}
APK_PACKAGES="$APK_PACKAGES {{ . }}"
{{- end }}
{{- end }}
# GD拡張の依存パッケージを自動的に追加
{{- if .Values.python.additionalApkPackages }}
# ユーザー指定の追加APKパッケージ(Python用)
{{- range .Values.python.additionalApkPackages }}
APK_PACKAGES="$APK_PACKAGES {{ . }}"
{{- end }}
{{- end }}
# PHP拡張(gd / mbstring)の依存パッケージを自動的に追加
{{- if .Values.composer.additionalPhpExtensions }}
for ext in {{ join " " .Values.composer.additionalPhpExtensions }}; do
if [ "$ext" = "gd" ]; then
echo "GD extension detected, adding required dependencies..."
APK_PACKAGES="$APK_PACKAGES libpng-dev libjpeg-turbo-dev freetype-dev"
break
fi
if [ "$ext" = "mbstring" ]; then
echo "mbstring extension detected, adding required dependencies..."
APK_PACKAGES="$APK_PACKAGES oniguruma-dev"
fi
done
{{- end }}
@@ -107,7 +130,10 @@ spec:
echo "Installing Composer..."
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
cd /var/www/html
# Composer導入先(デフォルトはWebルート外の /composer)
# PHPからは require_once '{{ .Values.composer.workingDir | default "/composer" }}/vendor/autoload.php'; で読み込む
mkdir -p {{ .Values.composer.workingDir | default "/composer" }}
cd {{ .Values.composer.workingDir | default "/composer" }}
{{- if .Values.composer.enabled }}
# ユーザー定義のComposer設定
@@ -115,13 +141,13 @@ spec:
# composer.jsonファイルを使用
echo "Creating composer.json from values..."
cat > composer.json << 'COMPOSER_JSON_EOF'
{{ .Values.composer.composerJson }}
{{- .Values.composer.composerJson | trim | nindent 14 }}
COMPOSER_JSON_EOF
{{- if .Values.composer.composerLock }}
echo "Creating composer.lock from values..."
cat > composer.lock << 'COMPOSER_LOCK_EOF'
{{ .Values.composer.composerLock }}
{{- .Values.composer.composerLock | trim | nindent 14 }}
COMPOSER_LOCK_EOF
{{- end }}
@@ -141,6 +167,13 @@ spec:
{{- end }}
{{- else }}
# 旧Webルート(/var/www/html)に composer.json がある場合は移行(v8.5.6-a以前からのアップグレード対応)
if [ ! -f composer.json ] && [ -f /var/www/html/composer.json ]; then
echo "Migrating legacy composer files from /var/www/html to $(pwd)..."
mv /var/www/html/composer.json ./composer.json
if [ -f /var/www/html/composer.lock ]; then mv /var/www/html/composer.lock ./composer.lock; fi
if [ -d /var/www/html/vendor ]; then mv /var/www/html/vendor ./vendor; fi
fi
# composer.jsonが既に存在する場合はそれを使用
if [ -f composer.json ]; then
echo "Found existing composer.json, running composer install..."
@@ -159,6 +192,38 @@ spec:
{{- end }}
{{- end }}
{{- if .Values.python.enabled }}
{{- $pythonDir := .Values.python.venvDir | default "/venv" }}
# ========================================
# Python仮想環境のセットアップ
# ========================================
echo "Setting up Python virtual environment..."
# Python導入先(デフォルトはWebルート外の /venv、Composerと同様の使い捨て領域)
# PHPからの呼び出し方: exec('{{ $pythonDir }}/bin/python3 /path/to/script.py 2>&1', $output, $exitCode);
python3 -m venv {{ $pythonDir }}
{{- if .Values.python.useRequirementsTxt }}
echo "Creating requirements.txt from values..."
cat > /tmp/requirements.txt << 'REQUIREMENTS_TXT_EOF'
{{- .Values.python.requirementsTxt | trim | nindent 14 }}
REQUIREMENTS_TXT_EOF
echo "Installing Python packages from requirements.txt..."
{{ $pythonDir }}/bin/pip install {{ .Values.python.installOptions }} -r /tmp/requirements.txt
rm -f /tmp/requirements.txt
{{- else if .Values.python.packages }}
echo "Installing Python packages..."
{{- range .Values.python.packages }}
{{ $pythonDir }}/bin/pip install {{ $.Values.python.installOptions }} "{{ . }}"
{{- end }}
{{- else }}
echo "No Python package configuration found, virtual environment created without additional packages"
{{- end }}
{{- end }}
{{- if .Values.smtp.enabled }}
# ========================================
# SMTP設定(msmtp)
@@ -166,8 +231,12 @@ spec:
echo "Configuring SMTP for mail sending..."
# msmtprc設定ファイルをコピー
# msmtpはPHP-FPMワーカー(www-data等の非root)から実行されるため、
# rootが作成するこのファイルも読み取り可にする必要がある
# (実パスワードはpasswordeval経由で別ファイルから取得するため、
# msmtprc自体に平文パスワードは含まれない)
cp /etc/smtp-config/msmtprc /etc/msmtprc
chmod 600 /etc/msmtprc
chmod 644 /etc/msmtprc
# PHP設定をphp.ini.d/に作成
cat > /usr/local/etc/php/conf.d/99-smtp.ini << 'PHP_SMTP_EOF'
@@ -183,13 +252,26 @@ spec:
{{- end }}
echo "Setup complete, starting PHP-FPM..."
php-fpm
# exec で php-fpm をコンテナの PID1 に置き換える。
# 目的: setup シェルを介さず php-fpm 自身が SIGTERM/SIGKILL を直接受け取れる
# ようにする。シェルは既定で子プロセスへシグナルを転送しないため、exec せず
# `php-fpm`(子)のまま起動すると、コンテナ再起動時にシェル(PID1)だけが落ちて
# 旧 php-fpm が一時的に残存し、9000 を握ったまま次回起動が
# 「unable to bind ... '9000': Address in use」で失敗して CrashLoopBackOff に陥る。
# exec すれば php-fpm が PID1 になり、停止時に 9000 が確実に解放される。
# -F(--nodaemonize): 設定に依存せず必ずフォアグラウンドで起動する
# (デーモン化して master が背後に残る事故を防ぐ)。
exec php-fpm -F
ports:
- containerPort: 9000 # PHP-FPMは9000ポートでリッスン
volumeMounts:
# PVCルートを /var/www にマウント
# - /var/www/html のみ nginx が公開(nginx側は html サブパスだけをマウント)
# - それ以外(/var/www/<任意>)は非公開ファイルの格納先として利用可能
# ※ Composer導入先(デフォルト /composer)は意図的にマウントしない:
# Pod再起動のたびにクリーンな環境へ再構築される使い捨て領域とする
- name: app-storage
mountPath: /var/www/html
subPath: html
mountPath: /var/www
{{- if and .Values.composer.enabled .Values.composer.useComposerJson }}
- name: composer-config
mountPath: /tmp/composer-init
@@ -220,6 +302,10 @@ spec:
name: {{ include "phpfpm.fullname" . }}-db-secret
key: {{ include "phpfpm.fullname" . }}-db-key
{{- end }}
{{- range $key, $value := .Values.phpEnv }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- if .Values.selenium.enabled }}
- name: selenium
image: "{{ .Values.image.selenium.registry }}/{{ .Values.image.selenium.repository }}:{{ .Values.image.selenium.tag }}"
@@ -266,6 +352,9 @@ spec:
items:
- key: password
path: password
mode: 0600
# 0600だとSecretボリュームの所有者はroot、
# msmtpはPHP-FPMワーカー(www-data等の非root)から実行されるため読めない
# → 全ユーザー読み取り可にする(ボリュームはPod内にしか存在しないため許容範囲)
mode: 0644
{{- end }}
{{- end }}
+3 -1
View File
@@ -6,7 +6,9 @@ metadata:
labels:
{{- include "phpfpm.labels" . | nindent 4 }}
annotations:
{{- toYaml .Values.ingress.annotations | nindent 4 }}
{{- /* uploadMaxSize を ingress-nginx の proxy-body-size に自動反映(明示指定があればそちらを優先) */}}
{{- $ingressAnnotations := merge (deepCopy .Values.ingress.annotations) (dict "nginx.ingress.kubernetes.io/proxy-body-size" .Values.uploadMaxSize) }}
{{- toYaml $ingressAnnotations | nindent 4 }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
+75 -5
View File
@@ -4,17 +4,17 @@ image:
nginx:
registry: docker.io
repository: nginx
tag: "1.29.6-alpine-perl"
tag: "1.31.5-alpine-perl"
pullPolicy: IfNotPresent
php:
registry: docker.io
repository: php
tag: "8.5.4-fpm-alpine3.23"
tag: "8.5.10-fpm-alpine3.24"
pullPolicy: IfNotPresent
selenium:
registry: docker.io
repository: selenium/standalone-chromium
tag: "145.0-chromedriver-145.0"
tag: "152.0-chromedriver-152.0"
pullPolicy: IfNotPresent
service:
@@ -22,15 +22,25 @@ service:
type: LoadBalancer
port: 80
# アップロード可能な最大サイズ
# 以下3箇所に同じ値を反映する(どれか一つでも小さいと、そこで上限に達して失敗するため):
# - nginx(Podコンテナ内)の client_max_body_size
# - PHPの upload_max_filesize / post_max_size
# - ingress.enabled: true の場合、ingress-nginxの nginx.ingress.kubernetes.io/proxy-body-size
# 単位はnginx/PHP共通でk/m/g(大文字小文字問わず)が使用可能(例: "100m", "1g")
uploadMaxSize: "100m"
ingress:
enabled: false
className: ""
# nginx.ingress.kubernetes.io/proxy-body-size は uploadMaxSize の値が自動的に付与されるため
# 明示的に指定する必要はない(Ingress側の上限もnginx/PHPと揃う)
# 別の値にしたい場合や別コントローラーを使う場合は、ここに明示指定すれば上書きされる
annotations: {}
# {
# acme.cert-manager.io/http01-ingress-class: "nginx",
# cert-manager.io/cluster-issuer: "letsencrypt-issuer",
# nginx.ingress.kubernetes.io/from-to-www-redirect: "true",
# nginx.ingress.kubernetes.io/proxy-body-size: "100m"
# nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
# }
hosts:
- host: example.tld
@@ -85,6 +95,19 @@ composer:
# Composerを使用するかどうか
enabled: false
# Composerの導入先ディレクトリ(composer.json / vendor の配置先)
# デフォルトの /composer はWebルート外かつPVCにマウントされない「使い捨て」領域:
# - vendor/ や composer.json がWeb経由で公開されない
# - Pod再起動のたびにクリーンな環境へ再構築されるため、
# 不正アクセスでマルウェアを書き込まれても再起動で消える
#
# 【重要】PHPコードからの autoload.php の読み込み方:
# require_once '/composer/vendor/autoload.php';
#
# PVC上に永続化したい場合は /var/www 配下(例: "/var/www/composer")を指定
# 旧来の動作(Webルート直下に導入)へ戻す場合は "/var/www/html" を指定
workingDir: "/composer"
# Composerでインストールするパッケージ
# packages配列が空の場合、composer.jsonを使用
packages: []
@@ -118,6 +141,44 @@ composer:
# - "gd"
# - "zip"
# Python設定(オプション、PHPからPythonスクリプトを呼び出す用途)
python:
# Pythonを使用するかどうか
enabled: false
# Python仮想環境(venv)の導入先ディレクトリ
# デフォルトの /venv はWebルート外かつPVCにマウントされない「使い捨て」領域:
# - Pod再起動のたびにクリーンな環境へ再構築される(Composerと同じ設計)
#
# 【重要】PHPからのPython呼び出し方(execを利用):
# exec('/venv/bin/python3 /path/to/script.py 2>&1', $output, $exitCode);
#
# PVC上に永続化したい場合は /var/www 配下(例: "/var/www/venv")を指定
venvDir: "/venv"
# pipでインストールするパッケージ
# packages配列が空の場合、requirements.txtを使用
packages: []
# - "requests>=2.31.0"
# - "pillow"
# requirements.txtを使用する場合
useRequirementsTxt: false
# requirements.txtの内容(useRequirementsTxt: trueの場合に使用)
requirementsTxt: |
requests>=2.31.0
# pip installのオプション
installOptions: "--no-cache-dir"
# 追加のAPKパッケージ(ネイティブ拡張のビルドに必要な場合、例: numpy等)
additionalApkPackages: []
# - "gcc"
# - "musl-dev"
# - "python3-dev"
# - "jpeg-dev"
# Selenium設定(レガシー互換性維持)
selenium:
enabled: false
@@ -174,3 +235,12 @@ smtp:
allowSelfSigned: false
resources: {}
# PHP-FPM コンテナに渡す任意の環境変数
# DB接続情報(externalDatabase)と同様に、values.yamlで設定した値がPHPに環境変数として渡される
# PHPからは $_ENV['KEY'] または getenv('KEY') で取得可能
phpEnv: {}
# API_KEY: "your-api-key"
# STRIPE_SECRET: "sk_live_xxxxxxxxxxxxxxxx"
# REDIS_URL: "redis://localhost:6379"
# SOME_SERVICE_URL: "https://api.example.com"