From cbdf29cb61a5f78fa329b083c3754e3586be8794 Mon Sep 17 00:00:00 2001 From: atsu666 Date: Wed, 8 Dec 2021 16:07:45 +0900 Subject: [PATCH 01/20] =?UTF-8?q?php8.1=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4428f76..93566e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.0.13-apache +FROM php:8.1-apache # extension RUN apt-get update \ From 989f26932bc1c0d398885214b73c0457cd19d5ec Mon Sep 17 00:00:00 2001 From: atsu666 Date: Sat, 11 Dec 2021 12:02:15 +0900 Subject: [PATCH 02/20] =?UTF-8?q?redis=E6=8B=A1=E5=BC=B5=E3=82=92=E5=B0=8E?= =?UTF-8?q?=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 93566e2..ea47752 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,9 +34,11 @@ RUN apt-get update \ && pecl install xdebug \ imagick \ apcu \ + redis \ && docker-php-ext-enable xdebug \ && docker-php-ext-enable imagick \ && docker-php-ext-enable apcu \ + && docker-php-ext-enable redis \ && ln -s /usr/bin/python2.7 /usr/bin/python # composer From 6a95dc05327e8b4ac68eb6e77ae9eed0f1872f6c Mon Sep 17 00:00:00 2001 From: atsu666 Date: Thu, 19 May 2022 16:56:45 +0900 Subject: [PATCH 03/20] =?UTF-8?q?xdebug=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index ea47752..0d63840 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,11 +31,9 @@ RUN apt-get update \ && docker-php-ext-install mysqli \ && docker-php-ext-install opcache \ && docker-php-ext-enable mysqli \ - && pecl install xdebug \ - imagick \ + && pecl install imagick \ apcu \ redis \ - && docker-php-ext-enable xdebug \ && docker-php-ext-enable imagick \ && docker-php-ext-enable apcu \ && docker-php-ext-enable redis \ From a7847490ec610c5b33a9453f1270c73adf125ee7 Mon Sep 17 00:00:00 2001 From: atsu666 Date: Wed, 6 Jul 2022 15:47:57 +0900 Subject: [PATCH 04/20] =?UTF-8?q?mod:=20headers,=20mime,=20expires,=20defl?= =?UTF-8?q?ate=20=E3=82=92=E6=9C=89=E5=8A=B9=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Conflicts: # Dockerfile --- Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0d63840..5d79171 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,11 @@ RUN apt-get update \ && docker-php-ext-enable imagick \ && docker-php-ext-enable apcu \ && docker-php-ext-enable redis \ - && ln -s /usr/bin/python2.7 /usr/bin/python + && ln -s /usr/bin/python2.7 /usr/bin/python \ + && a2enmod headers \ + && a2enmod mime \ + && a2enmod expires \ + && a2enmod deflate # composer RUN curl -S https://getcomposer.org/installer | php \ From 2012741bac711ec9d1783ec00a6b26ac576cd77d Mon Sep 17 00:00:00 2001 From: atsu666 Date: Wed, 9 Feb 2022 12:25:52 +0900 Subject: [PATCH 05/20] =?UTF-8?q?=E5=86=8D=E8=B5=B7=E5=8B=95=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=81=A8=E3=80=81=E3=83=89=E3=82=AD=E3=83=A5=E3=83=A1?= =?UTF-8?q?=E3=83=B3=E3=83=88=E3=83=AB=E3=83=BC=E3=83=88=E3=81=8C=E3=81=9A?= =?UTF-8?q?=E3=82=8C=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entrypoint.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 14c1934..a3ca4fd 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -9,9 +9,14 @@ echo "127.0.0.1 $(hostname).localdomain $(hostname)" >> /etc/hosts # document root echo "${APACHE_DOCUMENT_ROOT}" +INIT_FILE="/var/www/init.txt" + if test "${APACHE_DOCUMENT_ROOT}" != ""; then - sed -ri -e "s!/var/www/html!${APACHE_DOCUMENT_ROOT}!g" /etc/apache2/sites-available/*.conf - sed -ri -e "s!/var/www/!${APACHE_DOCUMENT_ROOT}!g" /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf + if [ ! -e $INIT_FILE ]; then + sed -ri -e "s!/var/www/html!${APACHE_DOCUMENT_ROOT}!g" /etc/apache2/sites-available/*.conf + sed -ri -e "s!/var/www/!${APACHE_DOCUMENT_ROOT}!g" /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf + touch $INIT_FILE + fi fi service sendmail restart From 3ab2ffddab26b96b95e3b5900b6c908b16250b92 Mon Sep 17 00:00:00 2001 From: atsu666 Date: Thu, 22 Dec 2022 10:40:01 +0900 Subject: [PATCH 06/20] =?UTF-8?q?apple=20silicon=20(arm64)=20=E3=81=AB?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 5d79171..2b64895 100644 --- a/Dockerfile +++ b/Dockerfile @@ -61,6 +61,7 @@ RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.s COPY config/php.ini /usr/local/etc/php/ # apache +RUN echo "Mutex posixsem" >> /etc/apache2/apache2.conf RUN a2enmod rewrite RUN a2enmod ssl From 5faa385a0caa75b78642f637bc87068730702681 Mon Sep 17 00:00:00 2001 From: atsu666 Date: Thu, 22 Dec 2022 10:41:57 +0900 Subject: [PATCH 07/20] =?UTF-8?q?linux/amd64=E3=81=AE=E3=82=A4=E3=83=A1?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=82=92=E6=8C=81=E3=81=A3=E3=81=A6=E3=81=8F?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2b64895..7f6f504 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.1-apache +FROM --platform=linux/amd64 php:8.1-apache # extension RUN apt-get update \ From 783a41c4f7a8ef7ca140e9b3511008ce67a76201 Mon Sep 17 00:00:00 2001 From: atsu666 Date: Thu, 22 Dec 2022 11:37:00 +0900 Subject: [PATCH 08/20] =?UTF-8?q?=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7f6f504..2b64895 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 php:8.1-apache +FROM php:8.1-apache # extension RUN apt-get update \ From fd78f9e7a963e4bcbe88c3f77ba32d5105312212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Mon, 19 Feb 2024 16:28:27 +0900 Subject: [PATCH 09/20] =?UTF-8?q?PHP8.2=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2b64895..76aac14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.1-apache +FROM php:8.2-apache # extension RUN apt-get update \ @@ -19,7 +19,7 @@ RUN apt-get update \ git-core \ build-essential \ openssl \ - python2.7 \ + python3 \ zip \ unzip \ && docker-php-ext-configure gd --with-jpeg \ @@ -30,6 +30,7 @@ RUN apt-get update \ && docker-php-ext-install pdo_mysql \ && docker-php-ext-install mysqli \ && docker-php-ext-install opcache \ + && docker-php-ext-install bcmath \ && docker-php-ext-enable mysqli \ && pecl install imagick \ apcu \ @@ -37,7 +38,7 @@ RUN apt-get update \ && docker-php-ext-enable imagick \ && docker-php-ext-enable apcu \ && docker-php-ext-enable redis \ - && ln -s /usr/bin/python2.7 /usr/bin/python \ + && ln -s /usr/bin/python3 /usr/bin/python \ && a2enmod headers \ && a2enmod mime \ && a2enmod expires \ From 95b18d0b30e60aba3acdf8b5d83fb049a925906a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Mon, 19 Feb 2024 18:37:17 +0900 Subject: [PATCH 10/20] =?UTF-8?q?php8.3=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 76aac14..d9b6036 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.2-apache +FROM php:8.3-apache # extension RUN apt-get update \ @@ -32,10 +32,8 @@ RUN apt-get update \ && docker-php-ext-install opcache \ && docker-php-ext-install bcmath \ && docker-php-ext-enable mysqli \ - && pecl install imagick \ - apcu \ + && pecl install apcu \ redis \ - && docker-php-ext-enable imagick \ && docker-php-ext-enable apcu \ && docker-php-ext-enable redis \ && ln -s /usr/bin/python3 /usr/bin/python \ From 44dbcc8e9fa834e3c955aa998325ece708aacfd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Thu, 2 Jul 2026 21:37:52 +0900 Subject: [PATCH 11/20] =?UTF-8?q?=E5=8D=98=E4=B8=80=E3=83=96=E3=83=A9?= =?UTF-8?q?=E3=83=B3=E3=83=81=20+=20docker-bake=20=E6=A7=8B=E6=88=90?= =?UTF-8?q?=E3=81=B8=E5=88=B7=E6=96=B0=E3=81=97=20PHP=208.0-8.5=20?= =?UTF-8?q?=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ブランチごとに Dockerfile を分ける方式から、単一ブランチ + docker-bake.hcl (PHP_VERSIONS が唯一の版一覧)+ 引数化した 1 枚の Dockerfile へ移行。 wpdev-docker-images の構成を参考にした。 - 対応 PHP: 8.0/8.1/8.2/8.3/8.4/8.5(マルチアーキ amd64/arm64) - xdebug/pcov を同梱し実行時トグル(ACMS_XDEBUG / -d pcov.enabled=1)。 -xdebug 専用イメージを廃止 - exif 追加・imagick 復活・Node(nvm) 削除 - PHP 8.5 の OPcache 静的組込みに対応(未ロード時のみ enable) - Composer をハッシュ検証してインストール、pecl 拡張を版固定、set -eux - 非 root 実行の UID/GID 実行時マッピング(ACMS_UID/ACMS_GID)、HEALTHCHECK - CI: build.yml(Docker Hub 公開/provenance/SBOM) / pr-preview.yml(GHCR) / lint.yml(actionlint)。Actions は commit SHA でピン留め、dependabot 追加 - 公開先 appleple/acms-dev(実行環境)。appleple/acms は将来の同梱版に予約 Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/dependabot.yml | 14 ++++ .github/workflows/build.yml | 64 ++++++++++++++ .github/workflows/lint.yml | 31 +++++++ .github/workflows/pr-preview.yml | 62 ++++++++++++++ .gitignore | 3 +- Dockerfile | 99 +++++++++++++--------- README.md | 139 ++++++++++++++++++++++++------- config/pcov.ini | 8 ++ config/xdebug.ini | 8 ++ docker-bake.hcl | 83 ++++++++++++++++++ entrypoint.sh | 32 ++++++- 11 files changed, 469 insertions(+), 74 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/pr-preview.yml create mode 100644 config/pcov.ini create mode 100644 config/xdebug.ini create mode 100644 docker-bake.hcl diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..0c860b9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +# GitHub Actions の更新を自動追従する(週次)。 +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 20 + groups: + github-actions: + update-types: + - minor + - patch diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..9b34998 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,64 @@ +# master への push / 週次 / 手動実行で Docker Hub (appleple) へマルチアーキ公開する。 +# ビルド対象バージョンは docker-bake.hcl の PHP_VERSIONS が単一の真実の源。 +# PR のプレビュービルドは pr-preview.yml(GHCR)が担当する。 +# +# 必要な Secrets: DOCKERHUB_USERNAME / DOCKERHUB_TOKEN +# Actions は commit SHA でピン留め(サプライチェーン対策)。更新は dependabot。 +name: Build and publish images + +on: + push: + branches: + - master + paths: + - 'Dockerfile' + - 'entrypoint.sh' + - 'config/**' + - 'docker-bake.hcl' + - '.github/workflows/build.yml' + workflow_dispatch: + # 毎週日曜 00:00 UTC。ベースイメージのセキュリティ更新を取り込む定期ビルド。 + schedule: + - cron: '0 0 * * 0' + +concurrency: + group: ${{ github.workflow }}-${{ github.sha }} + cancel-in-progress: true + +permissions: {} + +jobs: + build: + name: Build PHP images (bake matrix) + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Set up QEMU + uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 + + - name: Login to Docker Hub + uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push (multi-arch) + uses: docker/bake-action@d3418bd7d0e9324001bca92fa8ba175ea7e6dc9b # v7.3.0 + with: + source: . + push: true + set: | + *.cache-from=type=gha + *.cache-to=type=gha,mode=max + *.attest=type=provenance,mode=max + *.attest=type=sbom diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..35d91e8 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,31 @@ +# GitHub Actions ワークフローの静的検査(actionlint)。YAML/式/シェルの事故を防ぐ。 +name: Lint workflows + +on: + pull_request: + paths: + - '.github/workflows/**' + push: + branches: + - master + paths: + - '.github/workflows/**' + +permissions: {} + +jobs: + actionlint: + name: actionlint + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Run actionlint + uses: reviewdog/action-actionlint@be0761e4c1bab7cfdfca56cd03d4bb6253e39a4a # v1.72.0 + with: + reporter: github-check diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml new file mode 100644 index 0000000..7e3c35a --- /dev/null +++ b/.github/workflows/pr-preview.yml @@ -0,0 +1,62 @@ +# Pull Request ごとに GHCR へプレビューイメージを公開する(レビュアーが pull 可能)。 +# タグ例: ghcr.io//docker-acms/acms:8.3- +# フォークからの PR は GITHUB_TOKEN に packages:write が無いため、ビルド検証のみ。 +name: Build preview images (PR) + +on: + pull_request: + paths: + - 'Dockerfile' + - 'entrypoint.sh' + - 'config/**' + - 'docker-bake.hcl' + - '.github/workflows/pr-preview.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + build: + name: Build preview (bake matrix) + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + env: + # 同一リポジトリの PR のみ GHCR へ push(フォークは検証のみ) + IS_INTERNAL: ${{ github.event.pull_request.head.repo.full_name == github.repository }} + # bake の HCL 変数は同名の環境変数で上書きできる + REGISTRY: ghcr.io/${{ github.repository_owner }}/docker-acms + PR_TAG: -${{ github.event.number }} + + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Set up QEMU + uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 + + - name: Login to GHCR + if: ${{ env.IS_INTERNAL == 'true' }} + uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build (push preview when internal) + uses: docker/bake-action@d3418bd7d0e9324001bca92fa8ba175ea7e6dc9b # v7.3.0 + with: + source: . + push: ${{ env.IS_INTERNAL == 'true' }} + set: | + *.cache-from=type=gha + *.cache-to=type=gha,mode=max diff --git a/.gitignore b/.gitignore index 496ee2c..c485a13 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.DS_Store \ No newline at end of file +.DS_Store +docs diff --git a/Dockerfile b/Dockerfile index d9b6036..7e65e89 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,27 @@ -FROM php:8.3-apache +# syntax=docker/dockerfile:1 -# extension -RUN apt-get update \ - && apt-get install -y \ +# ビルドするPHPバージョンは docker-bake.hcl / CI のマトリクスから渡す。 +# ローカルで単体ビルドする場合は --build-arg PHP_VERSION=8.3 を指定する。 +ARG PHP_VERSION=8.3 +FROM php:${PHP_VERSION}-apache + +# pecl 拡張のバージョンは再現性のため固定(PHP 8.0〜8.5 でビルド確認済み)。 +# 更新は手動(dependabot は pecl を追わない)。新 PHP 対応時はここを見直す。 +ARG APCU_VERSION=5.1.28 +ARG REDIS_VERSION=6.3.0 +ARG IMAGICK_VERSION=3.8.1 +ARG XDEBUG_VERSION=3.5.3 +ARG PCOV_VERSION=1.0.12 + +# ---- OS パッケージ & PHP 拡張 ---- +# xdebug/pcov は常時インストールしておき、有効化は実行時に行う。 +# - xdebug: ACMS_XDEBUG=true のときだけ entrypoint が有効化(-xdebug 専用イメージ不要) +# - pcov: 既定は pcov.enabled=0(カバレッジ取得時のみ -d pcov.enabled=1) +# OPcache は PHP 8.5 で静的組込みのため install せず、未ロード時のみ enable する +# (8.0=要enable / 8.3=標準で有効 / 8.5=静的、を1行で吸収)。 +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ libfreetype6-dev \ libmagickwand-dev \ libjpeg62-turbo-dev \ @@ -22,49 +41,49 @@ RUN apt-get update \ python3 \ zip \ unzip \ - && docker-php-ext-configure gd --with-jpeg \ - && docker-php-ext-install -j$(nproc) gd \ - && docker-php-ext-install -j$(nproc) zip \ - && docker-php-ext-install mbstring \ - && docker-php-ext-install gettext \ - && docker-php-ext-install pdo_mysql \ - && docker-php-ext-install mysqli \ - && docker-php-ext-install opcache \ - && docker-php-ext-install bcmath \ - && docker-php-ext-enable mysqli \ - && pecl install apcu \ - redis \ - && docker-php-ext-enable apcu \ - && docker-php-ext-enable redis \ - && ln -s /usr/bin/python3 /usr/bin/python \ - && a2enmod headers \ - && a2enmod mime \ - && a2enmod expires \ - && a2enmod deflate - -# composer -RUN curl -S https://getcomposer.org/installer | php \ - && mv composer.phar /usr/local/bin/composer \ - && composer self-update + ; \ + docker-php-ext-configure gd --with-freetype --with-jpeg; \ + docker-php-ext-install -j"$(nproc)" gd zip; \ + docker-php-ext-install mbstring gettext pdo_mysql mysqli bcmath exif; \ + docker-php-ext-enable mysqli; \ + php -m | grep -qi 'Zend OPcache' || docker-php-ext-enable opcache; \ + pecl install "apcu-${APCU_VERSION}"; \ + pecl install "redis-${REDIS_VERSION}"; \ + pecl install "imagick-${IMAGICK_VERSION}"; \ + pecl install "xdebug-${XDEBUG_VERSION}"; \ + pecl install "pcov-${PCOV_VERSION}"; \ + docker-php-ext-enable apcu redis imagick pcov; \ + ln -sf /usr/bin/python3 /usr/bin/python; \ + a2enmod headers mime expires deflate rewrite ssl; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* -# node -RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash \ - && export NVM_DIR="$HOME/.nvm" \ - && . $NVM_DIR/nvm.sh \ - && nvm install v14.16.0 \ - && nvm use v14.16.0 \ - && nvm alias default v14.16.0 \ - && npm install -g npm +# composer(インストーラの署名を SHA-384 で検証してから実行:改ざん対策) +RUN set -eux; \ + curl -fsSL -o /tmp/composer-setup.php https://getcomposer.org/installer; \ + curl -fsSL -o /tmp/composer-setup.sig https://composer.github.io/installer.sig; \ + php -r "\$sig = trim(file_get_contents('/tmp/composer-setup.sig')); \$hash = hash('sha384', file_get_contents('/tmp/composer-setup.php')); if (\$sig !== \$hash) { fwrite(STDERR, 'Composer installer integrity check failed'.PHP_EOL); exit(1); }"; \ + php /tmp/composer-setup.php --no-ansi --install-dir=/usr/local/bin --filename=composer; \ + composer --ansi --version --no-interaction; \ + rm -f /tmp/composer-setup.php /tmp/composer-setup.sig # php.ini COPY config/php.ini /usr/local/etc/php/ +# PCOV(コードカバレッジ用。既定は無効。実行時に -d pcov.enabled=1 で有効化) +COPY config/pcov.ini /usr/local/etc/php/conf.d/zz-pcov.ini + +# xdebug 設定は conf.d に置かず、entrypoint が有効化時のみ読み込む +COPY config/xdebug.ini /usr/local/etc/php/xdebug.ini + # apache RUN echo "Mutex posixsem" >> /etc/apache2/apache2.conf -RUN a2enmod rewrite -RUN a2enmod ssl COPY entrypoint.sh /usr/local/bin/ -RUN ["chmod", "+x", "/usr/local/bin/entrypoint.sh"] +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Apache が接続を受け付けているかの簡易チェック(接続不可のときだけ unhealthy) +HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ + CMD curl -sS -o /dev/null http://localhost/ || exit 1 -ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/README.md b/README.md index 0f294b6..0b5fa8e 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,115 @@ # a-blog cms Docker Images -## example +a-blog cms 開発用の **実行環境イメージ(Apache + PHP、a-blog cms 非同梱)** です。 +自分の a-blog cms プロジェクトをマウントして使います。 +**すべての PHP バージョンを 1 つのブランチ(master)で管理**し、`docker buildx bake` でビルドします。 -run docker-compose up +### 名前空間の設計 -``` -version: '2' +| リポジトリ | 中身 | 本リポジトリ | +|---|---|---| +| `appleple/acms` | a-blog cms **同梱**・すぐ動くプロダクト(将来公開予定)| — | +| `appleple/acms-dev` | PHP+Apache **実行環境のみ**(非同梱・マウント運用)| ✅ これを公開 | + +## 提供イメージ + +| タグ | 内容 | +|------|------| +| `appleple/acms-dev:8.0` | PHP 8.0 + Apache | +| `appleple/acms-dev:8.1` | PHP 8.1 + Apache | +| `appleple/acms-dev:8.2` | PHP 8.2 + Apache | +| `appleple/acms-dev:8.3` | PHP 8.3 + Apache(`latest` と同一)| +| `appleple/acms-dev:8.4` | PHP 8.4 + Apache | +| `appleple/acms-dev:8.5` | PHP 8.5 + Apache | +| `appleple/acms-dev:latest` | 最新安定版(現在 8.3)| + +いずれも `linux/amd64` と `linux/arm64`(Apple Silicon)のマルチアーキ対応です。 + +## 使い方(docker compose) + +```yaml services: - # mysql - mysql: - image: mysql:5.8 - ports: - - "3306:3306" - environment: - MYSQL_ROOT_PASSWORD: root - # proxy - proxy: - image: jwilder/nginx-proxy:latest - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - ports: - - "80:80" - - "443:443" - # www - www: - image: atsu666/acms:8.0 - privileged: true - volumes: - - ./www:/var/www/html - - /etc/localtime:/etc/localtime:ro - links: - - mysql:mysql - environment: - - VIRTUAL_HOST=example.lab - - APACHE_DOCUMENT_ROOT=/var/www/html + mysql: + image: mysql:8.0 + ports: + - "3306:3306" + environment: + MYSQL_ROOT_PASSWORD: root + + www: + image: appleple/acms-dev:8.3 + privileged: true + volumes: + - ./www:/var/www/html + - /etc/localtime:/etc/localtime:ro + ports: + - "80:80" + - "443:443" + depends_on: + - mysql + environment: + APACHE_DOCUMENT_ROOT: /var/www/html + # Xdebug を使う場合のみ true にする(既定は無効) + # ACMS_XDEBUG: "true" + # Linux ホストでボリューム所有権を合わせたい場合(任意) + # ACMS_UID: "1000" + # ACMS_GID: "1000" ``` +```sh +docker compose up +``` + +> `ACMS_UID`/`ACMS_GID` を渡すと Apache 実行ユーザ(www-data)の uid/gid をホストに合わせ、 +> マウント先に生成されるファイルの所有権ずれ(主に Linux ホスト)を防げます。macOS/Windows では通常不要です。 + +## Xdebug + +Xdebug はイメージに同梱されており、**専用イメージ(`-xdebug`)は不要**です。 +環境変数 `ACMS_XDEBUG=true` を渡すと起動時に有効化されます(同時に opcache は無効化)。 +設定は [`config/xdebug.ini`](config/xdebug.ini) にあり、IDE はポート `9003` で待ち受ける想定です。 + +## テスト・カバレッジ(コア開発向け) + +- **PCOV** を同梱しています(PHPUnit のカバレッジ取得用。Xdebug より高速)。 + 既定は無効(`pcov.enabled=0`)で、常時のオーバーヘッドはありません。取得時のみ有効化します: + ```sh + docker compose exec www php -d pcov.enabled=1 vendor/bin/phpunit --coverage-text + ``` + 設定は [`config/pcov.ini`](config/pcov.ini)。対象を絞る場合は `pcov.directory` を指定。 +- **exif** 拡張を同梱しています(EXIF Orientation を使う画像回転処理・テスト向け)。 +- カバレッジは PCOV と Xdebug のどちらか一方のみ使用してください(併用は非対応)。 + ステップ実行が必要なときだけ `ACMS_XDEBUG=true`、カバレッジは PCOV が推奨です。 + +> Node.js は同梱していません。テーマ/アセットのビルドはホストまたは別コンテナで行ってください。 + +## 開発(メンテナ向け) + +対応バージョンや拡張を変更するときは、以下のソースだけを編集します(生成物はありません)。 + +- `Dockerfile` — 全バージョン共通。PHP バージョンは `ARG PHP_VERSION` で受け取る +- `docker-bake.hcl` — 対応バージョン一覧(`PHP_VERSIONS`)とタグ・アーキの定義 +- `entrypoint.sh` / `config/*` — 起動処理・設定 + +```sh +# 展開されるターゲットとタグを確認 +docker buildx bake --print + +# 全バージョンをローカルビルド(ホストのアーキのみ) +docker buildx bake + +# 単一バージョンを load して動作確認(Apple Silicon 例) +docker buildx bake acms-dev-8-3 --set "*.platform=linux/arm64" --load + +# マルチアーキで公開(通常は CI が実行) +docker buildx bake --push +``` + +### CI(GitHub Actions) + +- `build.yml` — `master` への push / 週次 / 手動実行で **Docker Hub (`appleple/acms-dev`) へマルチアーキ公開**(provenance / SBOM 添付)。 +- `pr-preview.yml` — Pull Request で **GHCR にプレビューイメージを公開**(`ghcr.io//docker-acms/acms-dev:-`)。フォークからの PR はビルド検証のみ。 +- `lint.yml` — `actionlint` によるワークフロー静的検査。 + +公開には Secrets(`DOCKERHUB_USERNAME` / `DOCKERHUB_TOKEN`)が必要です。 +Actions は commit SHA でピン留めし、`dependabot` が更新 PR を出します。 diff --git a/config/pcov.ini b/config/pcov.ini new file mode 100644 index 0000000..81dd125 --- /dev/null +++ b/config/pcov.ini @@ -0,0 +1,8 @@ +; PCOV(PHPUnit 用の高速コードカバレッジドライバ) +; 常時有効だと全リクエストに計測コストが乗るため、既定は無効。 +; カバレッジ取得時のみ有効化する: +; php -d pcov.enabled=1 vendor/bin/phpunit --coverage-text +; もしくは phpunit.xml の 設定で pcov を使う。 +pcov.enabled = 0 +; 計測対象を絞ると高速化する。プロジェクトに合わせて調整(例: /var/www/html)。 +; pcov.directory = /var/www/html diff --git a/config/xdebug.ini b/config/xdebug.ini new file mode 100644 index 0000000..f25bf3f --- /dev/null +++ b/config/xdebug.ini @@ -0,0 +1,8 @@ +; Xdebug 3 用の設定。ACMS_XDEBUG=true のとき entrypoint.sh が conf.d へコピーする。 +; ホスト側(IDE)は 9003 番で待ち受ける想定。 +xdebug.mode = debug,develop +xdebug.start_with_request = yes +xdebug.client_host = host.docker.internal +xdebug.client_port = 9003 +xdebug.discover_client_host = true +xdebug.idekey = VSCODE diff --git a/docker-bake.hcl b/docker-bake.hcl new file mode 100644 index 0000000..6940047 --- /dev/null +++ b/docker-bake.hcl @@ -0,0 +1,83 @@ +# ============================================================================= +# a-blog cms Docker Images — ビルド定義(単一の真実の源) +# +# 対応PHPバージョンを増減するときは PHP_VERSIONS を編集するだけでよい。 +# CI もローカルもこの1ファイルを参照する。 +# +# ローカルで全バージョンをビルド(ホストのアーキのみ): +# docker buildx bake +# +# 単一バージョンをローカルに load して試す(Apple Silicon 例): +# docker buildx bake acms-dev-8-3 --set "*.platform=linux/arm64" --load +# +# マルチアーキで push(CI 相当): +# docker buildx bake --push +# +# 展開結果(ターゲット・タグ)の確認: +# docker buildx bake --print +# ============================================================================= + +# 公開先の Docker Hub 名前空間。実際に作成する組織名に合わせること +# (appleple が取得済みかは要確認。異なる場合はこの1行を変更)。 +variable "REGISTRY" { + default = "appleple" +} + +# このリポジトリが作るのは「実行環境のみ(a-blog cms 非同梱)」のイメージ。 +# 名前空間の設計: +# appleple/acms … 将来の「a-blog cms 同梱・すぐ動く」プロダクト(別途、private 想定) +# appleple/acms-dev … 本リポジトリが公開する実行環境(非同梱・マウント運用) +variable "IMAGE_NAME" { + default = "acms-dev" +} + +# latest タグを付与するバージョン +variable "PHP_LATEST" { + default = "8.3" +} + +# PR プレビュー用のタグ接尾辞(CI が - を渡す想定。通常は空) +variable "PR_TAG" { + default = "" +} + +# ビルド対象のマルチアーキ。CI では push と併せてこのまま使う。 +variable "PLATFORMS" { + default = ["linux/amd64", "linux/arm64"] +} + +# ---- ここがバージョン一覧の唯一の定義箇所 ---- +variable "PHP_VERSIONS" { + default = ["8.0", "8.1", "8.2", "8.3", "8.4", "8.5"] +} + +group "default" { + targets = ["acms-dev"] +} + +target "acms-dev" { + name = "acms-dev-${replace(php, ".", "-")}" + context = "." + dockerfile = "Dockerfile" + + matrix = { + php = PHP_VERSIONS + } + + args = { + PHP_VERSION = php + } + + platforms = PLATFORMS + + tags = concat( + ["${REGISTRY}/${IMAGE_NAME}:${php}${PR_TAG}"], + php == PHP_LATEST ? ["${REGISTRY}/${IMAGE_NAME}:latest${PR_TAG}"] : [] + ) + + labels = { + "org.opencontainers.image.title" = "a-blog cms dev runtime (PHP ${php})" + "org.opencontainers.image.source" = "https://github.com/appleple/docker-acms" + "org.opencontainers.image.description" = "Apache + PHP ${php} runtime for a-blog cms development (a-blog cms is NOT bundled; mount your project)" + } +} diff --git a/entrypoint.sh b/entrypoint.sh index a3ca4fd..fd80545 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -3,9 +3,37 @@ set -eo pipefail shopt -s nullglob -# sendmail +# sendmail 用のホスト名解決 echo "127.0.0.1 $(hostname).localdomain $(hostname)" >> /etc/hosts +# --- UID/GID マッピング(主に Linux ホストでのボリューム所有権対策)--- +# ACMS_UID / ACMS_GID を渡すと Apache 実行ユーザ(www-data)の uid/gid を合わせる。 +# 未指定なら従来どおり(何もしない)。 +if [ -n "${ACMS_GID}" ] && [ "${ACMS_GID}" != "$(id -g www-data)" ]; then + groupmod -o -g "${ACMS_GID}" www-data +fi +if [ -n "${ACMS_UID}" ] && [ "${ACMS_UID}" != "$(id -u www-data)" ]; then + usermod -o -u "${ACMS_UID}" www-data +fi + +# --- Xdebug の実行時トグル --- +# ACMS_XDEBUG=true のときだけ xdebug を有効化し、opcache を無効化する。 +# opcache の無効化は ini 設定で行う(PHP 8.5 は opcache が静的組込みのため +# ini 削除では止められない。opcache.enable=0 なら静的でも確実に無効化できる)。 +XDEBUG_INI="/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini" +XDEBUG_SETTINGS="/usr/local/etc/php/conf.d/zzz-xdebug-settings.ini" +OPCACHE_OFF="/usr/local/etc/php/conf.d/zzz-disable-opcache.ini" +if [ "${ACMS_XDEBUG}" = "true" ]; then + docker-php-ext-enable xdebug + cp /usr/local/etc/php/xdebug.ini "${XDEBUG_SETTINGS}" + printf 'opcache.enable=0\nopcache.enable_cli=0\n' > "${OPCACHE_OFF}" + echo "[entrypoint] Xdebug: enabled (opcache disabled)" +else + # 再起動時に備えて有効化状態を解除する + rm -f "${XDEBUG_INI}" "${XDEBUG_SETTINGS}" "${OPCACHE_OFF}" + echo "[entrypoint] Xdebug: disabled" +fi + # document root echo "${APACHE_DOCUMENT_ROOT}" @@ -27,4 +55,4 @@ trap 'service apache2 stop; exit 0' TERM while : do sleep 1 -done \ No newline at end of file +done From 6f2deefc64db5535f68dcd5ad6a7fdb2fec463e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Thu, 2 Jul 2026 21:44:40 +0900 Subject: [PATCH 12/20] =?UTF-8?q?=E7=92=B0=E5=A2=83=E5=A4=89=E6=95=B0?= =?UTF-8?q?=E3=81=AE=20ACMS=5F=20=E3=83=97=E3=83=AC=E3=83=95=E3=82=A3?= =?UTF-8?q?=E3=83=83=E3=82=AF=E3=82=B9=E3=82=92=E5=BB=83=E6=AD=A2=EF=BC=88?= =?UTF-8?q?XDEBUG=20/=20PUID=20/=20PGID=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ACMS_XDEBUG → XDEBUG - ACMS_UID / ACMS_GID → PUID / PGID (UID/GID は bash の読み取り専用特殊変数のため無印不可。PUID/PGID は Docker コミュニティの事実上の標準) Co-Authored-By: Claude Opus 4.8 (1M context) --- Dockerfile | 2 +- README.md | 12 ++++++------ config/xdebug.ini | 2 +- entrypoint.sh | 14 +++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7e65e89..ef91eee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ ARG PCOV_VERSION=1.0.12 # ---- OS パッケージ & PHP 拡張 ---- # xdebug/pcov は常時インストールしておき、有効化は実行時に行う。 -# - xdebug: ACMS_XDEBUG=true のときだけ entrypoint が有効化(-xdebug 専用イメージ不要) +# - xdebug: XDEBUG=true のときだけ entrypoint が有効化(-xdebug 専用イメージ不要) # - pcov: 既定は pcov.enabled=0(カバレッジ取得時のみ -d pcov.enabled=1) # OPcache は PHP 8.5 で静的組込みのため install せず、未ロード時のみ enable する # (8.0=要enable / 8.3=標準で有効 / 8.5=静的、を1行で吸収)。 diff --git a/README.md b/README.md index 0b5fa8e..641c969 100644 --- a/README.md +++ b/README.md @@ -50,23 +50,23 @@ services: environment: APACHE_DOCUMENT_ROOT: /var/www/html # Xdebug を使う場合のみ true にする(既定は無効) - # ACMS_XDEBUG: "true" + # XDEBUG: "true" # Linux ホストでボリューム所有権を合わせたい場合(任意) - # ACMS_UID: "1000" - # ACMS_GID: "1000" + # PUID: "1000" + # PGID: "1000" ``` ```sh docker compose up ``` -> `ACMS_UID`/`ACMS_GID` を渡すと Apache 実行ユーザ(www-data)の uid/gid をホストに合わせ、 +> `PUID`/`PGID` を渡すと Apache 実行ユーザ(www-data)の uid/gid をホストに合わせ、 > マウント先に生成されるファイルの所有権ずれ(主に Linux ホスト)を防げます。macOS/Windows では通常不要です。 ## Xdebug Xdebug はイメージに同梱されており、**専用イメージ(`-xdebug`)は不要**です。 -環境変数 `ACMS_XDEBUG=true` を渡すと起動時に有効化されます(同時に opcache は無効化)。 +環境変数 `XDEBUG=true` を渡すと起動時に有効化されます(同時に opcache は無効化)。 設定は [`config/xdebug.ini`](config/xdebug.ini) にあり、IDE はポート `9003` で待ち受ける想定です。 ## テスト・カバレッジ(コア開発向け) @@ -79,7 +79,7 @@ Xdebug はイメージに同梱されており、**専用イメージ(`-xdebug 設定は [`config/pcov.ini`](config/pcov.ini)。対象を絞る場合は `pcov.directory` を指定。 - **exif** 拡張を同梱しています(EXIF Orientation を使う画像回転処理・テスト向け)。 - カバレッジは PCOV と Xdebug のどちらか一方のみ使用してください(併用は非対応)。 - ステップ実行が必要なときだけ `ACMS_XDEBUG=true`、カバレッジは PCOV が推奨です。 + ステップ実行が必要なときだけ `XDEBUG=true`、カバレッジは PCOV が推奨です。 > Node.js は同梱していません。テーマ/アセットのビルドはホストまたは別コンテナで行ってください。 diff --git a/config/xdebug.ini b/config/xdebug.ini index f25bf3f..a7a4765 100644 --- a/config/xdebug.ini +++ b/config/xdebug.ini @@ -1,4 +1,4 @@ -; Xdebug 3 用の設定。ACMS_XDEBUG=true のとき entrypoint.sh が conf.d へコピーする。 +; Xdebug 3 用の設定。XDEBUG=true のとき entrypoint.sh が conf.d へコピーする。 ; ホスト側(IDE)は 9003 番で待ち受ける想定。 xdebug.mode = debug,develop xdebug.start_with_request = yes diff --git a/entrypoint.sh b/entrypoint.sh index fd80545..5d84ff3 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -7,23 +7,23 @@ shopt -s nullglob echo "127.0.0.1 $(hostname).localdomain $(hostname)" >> /etc/hosts # --- UID/GID マッピング(主に Linux ホストでのボリューム所有権対策)--- -# ACMS_UID / ACMS_GID を渡すと Apache 実行ユーザ(www-data)の uid/gid を合わせる。 +# PUID / PGID を渡すと Apache 実行ユーザ(www-data)の uid/gid を合わせる。 # 未指定なら従来どおり(何もしない)。 -if [ -n "${ACMS_GID}" ] && [ "${ACMS_GID}" != "$(id -g www-data)" ]; then - groupmod -o -g "${ACMS_GID}" www-data +if [ -n "${PGID}" ] && [ "${PGID}" != "$(id -g www-data)" ]; then + groupmod -o -g "${PGID}" www-data fi -if [ -n "${ACMS_UID}" ] && [ "${ACMS_UID}" != "$(id -u www-data)" ]; then - usermod -o -u "${ACMS_UID}" www-data +if [ -n "${PUID}" ] && [ "${PUID}" != "$(id -u www-data)" ]; then + usermod -o -u "${PUID}" www-data fi # --- Xdebug の実行時トグル --- -# ACMS_XDEBUG=true のときだけ xdebug を有効化し、opcache を無効化する。 +# XDEBUG=true のときだけ xdebug を有効化し、opcache を無効化する。 # opcache の無効化は ini 設定で行う(PHP 8.5 は opcache が静的組込みのため # ini 削除では止められない。opcache.enable=0 なら静的でも確実に無効化できる)。 XDEBUG_INI="/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini" XDEBUG_SETTINGS="/usr/local/etc/php/conf.d/zzz-xdebug-settings.ini" OPCACHE_OFF="/usr/local/etc/php/conf.d/zzz-disable-opcache.ini" -if [ "${ACMS_XDEBUG}" = "true" ]; then +if [ "${XDEBUG}" = "true" ]; then docker-php-ext-enable xdebug cp /usr/local/etc/php/xdebug.ini "${XDEBUG_SETTINGS}" printf 'opcache.enable=0\nopcache.enable_cli=0\n' > "${OPCACHE_OFF}" From 617961b28722a68bbed7df5e84a9bf94b9faf251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Fri, 3 Jul 2026 10:45:38 +0900 Subject: [PATCH 13/20] =?UTF-8?q?PHP=207.2/7.3/7.4=20=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=E3=81=97=E3=80=81README=20=E3=81=8B=E3=82=89=E5=90=8C?= =?UTF-8?q?=E6=A2=B1=E7=89=88=E3=82=A4=E3=83=A1=E3=83=BC=E3=82=B8=E3=81=AE?= =?UTF-8?q?=E8=A8=98=E8=BF=B0=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docker-bake.hcl の PHP_VERSIONS に 7.2/7.3/7.4 を追加(計 7.2〜8.5) - Dockerfile に 7.x 向けの条件分岐を追加 - 旧 Debian(buster/stretch) は apt ソースを archive.debian.org へ切替 - gd の configure フラグを PHP 7.4 未満で切替 - redis を PHP<7.4 で 5.3.7、xdebug を PHP<8.0 で 3.1.6 にフォールバック - imagick 3.8.1 / apcu 5.1.28 / pcov 1.0.12 は全バージョン共通 - README の名前空間説明(将来の同梱版)を削除(別リポジトリで公開予定のため) Co-Authored-By: Claude Opus 4.8 (1M context) --- Dockerfile | 32 +++++++++++++++++++++++++------- README.md | 10 +++------- docker-bake.hcl | 5 +---- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index ef91eee..5c54038 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,8 +5,8 @@ ARG PHP_VERSION=8.3 FROM php:${PHP_VERSION}-apache -# pecl 拡張のバージョンは再現性のため固定(PHP 8.0〜8.5 でビルド確認済み)。 -# 更新は手動(dependabot は pecl を追わない)。新 PHP 対応時はここを見直す。 +# pecl 拡張の既定バージョン(新しめの PHP 用。再現性のため固定)。 +# 古い PHP では下の RUN 内で対応する旧版へ自動的に切り替える。 ARG APCU_VERSION=5.1.28 ARG REDIS_VERSION=6.3.0 ARG IMAGICK_VERSION=3.8.1 @@ -17,9 +17,17 @@ ARG PCOV_VERSION=1.0.12 # xdebug/pcov は常時インストールしておき、有効化は実行時に行う。 # - xdebug: XDEBUG=true のときだけ entrypoint が有効化(-xdebug 専用イメージ不要) # - pcov: 既定は pcov.enabled=0(カバレッジ取得時のみ -d pcov.enabled=1) -# OPcache は PHP 8.5 で静的組込みのため install せず、未ロード時のみ enable する -# (8.0=要enable / 8.3=標準で有効 / 8.5=静的、を1行で吸収)。 +# OPcache は PHP 8.5 で静的組込みのため install せず、未ロード時のみ enable する。 +# PHP 7.x 対応のため、apt ソース(archive)・gd フラグ・redis/xdebug の版を分岐する。 RUN set -eux; \ + PHP_ID="$(php -r 'echo PHP_VERSION_ID;')"; \ + # 旧 Debian(buster/stretch)はアーカイブへ切替(apt-get update を通すため) + . /etc/os-release; \ + case "${VERSION_CODENAME:-}" in \ + buster|stretch) \ + sed -i 's|deb.debian.org|archive.debian.org|g; s|security.debian.org|archive.debian.org|g; /-updates/d' /etc/apt/sources.list; \ + ;; \ + esac; \ apt-get update; \ apt-get install -y --no-install-recommends \ libfreetype6-dev \ @@ -42,15 +50,25 @@ RUN set -eux; \ zip \ unzip \ ; \ - docker-php-ext-configure gd --with-freetype --with-jpeg; \ + # gd の configure フラグは PHP 7.4 で変わる + if [ "$PHP_ID" -ge 70400 ]; then \ + docker-php-ext-configure gd --with-freetype --with-jpeg; \ + else \ + docker-php-ext-configure gd --with-freetype-dir=/usr --with-jpeg-dir=/usr; \ + fi; \ docker-php-ext-install -j"$(nproc)" gd zip; \ docker-php-ext-install mbstring gettext pdo_mysql mysqli bcmath exif; \ docker-php-ext-enable mysqli; \ php -m | grep -qi 'Zend OPcache' || docker-php-ext-enable opcache; \ + # 版依存の pecl 拡張(古い PHP では対応する旧版へフォールバック) + REDIS_VER="$REDIS_VERSION"; \ + XDEBUG_VER="$XDEBUG_VERSION"; \ + if [ "$PHP_ID" -lt 70400 ]; then REDIS_VER=5.3.7; fi; \ + if [ "$PHP_ID" -lt 80000 ]; then XDEBUG_VER=3.1.6; fi; \ pecl install "apcu-${APCU_VERSION}"; \ - pecl install "redis-${REDIS_VERSION}"; \ + pecl install "redis-${REDIS_VER}"; \ pecl install "imagick-${IMAGICK_VERSION}"; \ - pecl install "xdebug-${XDEBUG_VERSION}"; \ + pecl install "xdebug-${XDEBUG_VER}"; \ pecl install "pcov-${PCOV_VERSION}"; \ docker-php-ext-enable apcu redis imagick pcov; \ ln -sf /usr/bin/python3 /usr/bin/python; \ diff --git a/README.md b/README.md index 641c969..0294b98 100644 --- a/README.md +++ b/README.md @@ -4,17 +4,13 @@ a-blog cms 開発用の **実行環境イメージ(Apache + PHP、a-blog cms 自分の a-blog cms プロジェクトをマウントして使います。 **すべての PHP バージョンを 1 つのブランチ(master)で管理**し、`docker buildx bake` でビルドします。 -### 名前空間の設計 - -| リポジトリ | 中身 | 本リポジトリ | -|---|---|---| -| `appleple/acms` | a-blog cms **同梱**・すぐ動くプロダクト(将来公開予定)| — | -| `appleple/acms-dev` | PHP+Apache **実行環境のみ**(非同梱・マウント運用)| ✅ これを公開 | - ## 提供イメージ | タグ | 内容 | |------|------| +| `appleple/acms-dev:7.2` | PHP 7.2 + Apache | +| `appleple/acms-dev:7.3` | PHP 7.3 + Apache | +| `appleple/acms-dev:7.4` | PHP 7.4 + Apache | | `appleple/acms-dev:8.0` | PHP 8.0 + Apache | | `appleple/acms-dev:8.1` | PHP 8.1 + Apache | | `appleple/acms-dev:8.2` | PHP 8.2 + Apache | diff --git a/docker-bake.hcl b/docker-bake.hcl index 6940047..4c65237 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -24,9 +24,6 @@ variable "REGISTRY" { } # このリポジトリが作るのは「実行環境のみ(a-blog cms 非同梱)」のイメージ。 -# 名前空間の設計: -# appleple/acms … 将来の「a-blog cms 同梱・すぐ動く」プロダクト(別途、private 想定) -# appleple/acms-dev … 本リポジトリが公開する実行環境(非同梱・マウント運用) variable "IMAGE_NAME" { default = "acms-dev" } @@ -48,7 +45,7 @@ variable "PLATFORMS" { # ---- ここがバージョン一覧の唯一の定義箇所 ---- variable "PHP_VERSIONS" { - default = ["8.0", "8.1", "8.2", "8.3", "8.4", "8.5"] + default = ["7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3", "8.4", "8.5"] } group "default" { From ccee6a43cf4cd5a4ae625a80dce559e8ad2a080f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Fri, 3 Jul 2026 11:53:55 +0900 Subject: [PATCH 14/20] Update README to clarify that the images are for development use --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0294b98..d99b2d0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# a-blog cms Docker Images +# a-blog cms Development Docker Images a-blog cms 開発用の **実行環境イメージ(Apache + PHP、a-blog cms 非同梱)** です。 自分の a-blog cms プロジェクトをマウントして使います。 From 4d0a37ff8d9d77fd7e4498d440cb5ad2aa70e175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Fri, 3 Jul 2026 11:55:58 +0900 Subject: [PATCH 15/20] =?UTF-8?q?latest=20=E3=82=BF=E3=82=B0=E3=82=92=208.?= =?UTF-8?q?5=20=E3=81=AB=E5=A4=89=E6=9B=B4=EF=BC=88PHP=5FLATEST=3D8.5?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docker-bake.hcl: PHP_LATEST 8.3 → 8.5 - README: 提供イメージ表の latest 表記を 8.5 に更新 Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 6 +++--- docker-bake.hcl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d99b2d0..7615e14 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,10 @@ a-blog cms 開発用の **実行環境イメージ(Apache + PHP、a-blog cms | `appleple/acms-dev:8.0` | PHP 8.0 + Apache | | `appleple/acms-dev:8.1` | PHP 8.1 + Apache | | `appleple/acms-dev:8.2` | PHP 8.2 + Apache | -| `appleple/acms-dev:8.3` | PHP 8.3 + Apache(`latest` と同一)| +| `appleple/acms-dev:8.3` | PHP 8.3 + Apache | | `appleple/acms-dev:8.4` | PHP 8.4 + Apache | -| `appleple/acms-dev:8.5` | PHP 8.5 + Apache | -| `appleple/acms-dev:latest` | 最新安定版(現在 8.3)| +| `appleple/acms-dev:8.5` | PHP 8.5 + Apache(`latest` と同一)| +| `appleple/acms-dev:latest` | 最新版(現在 8.5)| いずれも `linux/amd64` と `linux/arm64`(Apple Silicon)のマルチアーキ対応です。 diff --git a/docker-bake.hcl b/docker-bake.hcl index 4c65237..c33c8ed 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -30,7 +30,7 @@ variable "IMAGE_NAME" { # latest タグを付与するバージョン variable "PHP_LATEST" { - default = "8.3" + default = "8.5" } # PR プレビュー用のタグ接尾辞(CI が - を渡す想定。通常は空) From 48372608ccc8228e1465e906dc272963aa013d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Fri, 3 Jul 2026 13:21:32 +0900 Subject: [PATCH 16/20] =?UTF-8?q?PR=20=E3=83=97=E3=83=AC=E3=83=93=E3=83=A5?= =?UTF-8?q?=E3=83=BC=E3=82=92=E9=AB=98=E9=80=9F=E5=8C=96=EF=BC=88amd64?= =?UTF-8?q?=E3=83=BB=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3=E5=88=A5?= =?UTF-8?q?=20matrix=20=E4=B8=A6=E5=88=97=EF=BC=89=EF=BC=8B=20=E3=83=AA?= =?UTF-8?q?=E3=83=9D=E3=82=B8=E3=83=88=E3=83=AA=E5=90=8D=E3=82=92=E6=95=B4?= =?UTF-8?q?=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - pr-preview.yml: 全部入り multi-arch 1 runner → バージョン別 matrix で並列化。 PR は amd64 のみ(QEMU を廃止)。arm64 は本番 build.yml で維持。 対象バージョンは docker-bake.hcl から動的取得(二重管理しない)。 - GHCR 名前空間を ghcr.io/${{ github.repository }} に(リポジトリ改名へ自動追従)。 - OCI ラベル image.source / README を appleple/acms-development-docker-images に更新。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/pr-preview.yml | 52 ++++++++++++++++++++++++++------ README.md | 2 +- docker-bake.hcl | 2 +- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 7e3c35a..0cdff2e 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -1,5 +1,10 @@ # Pull Request ごとに GHCR へプレビューイメージを公開する(レビュアーが pull 可能)。 -# タグ例: ghcr.io//docker-acms/acms:8.3- +# タグ例: ghcr.io///acms-dev:8.5- +# +# 速度重視の構成: +# - PR では amd64 のみ(QEMU エミュレーションを使わない)。arm64 は本番 build.yml で。 +# - PHP バージョンごとに matrix で別 runner に分散(並列)。 +# - 対象バージョンは docker-bake.hcl から動的取得(二重管理しない)。 # フォークからの PR は GITHUB_TOKEN に packages:write が無いため、ビルド検証のみ。 name: Build preview images (PR) @@ -19,17 +24,45 @@ concurrency: permissions: {} jobs: + matrix: + name: Resolve build matrix + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + targets: ${{ steps.gen.outputs.targets }} + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 + + - name: Resolve bake targets from docker-bake.hcl + id: gen + run: | + targets="$(docker buildx bake --print 2>/dev/null | jq -c '[.target | keys[]]')" + echo "targets=$targets" >> "$GITHUB_OUTPUT" + build: - name: Build preview (bake matrix) + name: ${{ matrix.target }} (amd64) + needs: matrix runs-on: ubuntu-latest permissions: contents: read packages: write + strategy: + fail-fast: false + matrix: + target: ${{ fromJson(needs.matrix.outputs.targets) }} env: # 同一リポジトリの PR のみ GHCR へ push(フォークは検証のみ) IS_INTERNAL: ${{ github.event.pull_request.head.repo.full_name == github.repository }} - # bake の HCL 変数は同名の環境変数で上書きできる - REGISTRY: ghcr.io/${{ github.repository_owner }}/docker-acms + # bake の HCL 変数は同名の環境変数で上書きできる。 + # GHCR 名前空間はリポジトリ名に自動追従(改名にも強い) + REGISTRY: ghcr.io/${{ github.repository }} PR_TAG: -${{ github.event.number }} steps: @@ -38,9 +71,6 @@ jobs: with: persist-credentials: false - - name: Set up QEMU - uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 @@ -52,11 +82,13 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build (push preview when internal) + - name: Build (amd64; push preview when internal) uses: docker/bake-action@d3418bd7d0e9324001bca92fa8ba175ea7e6dc9b # v7.3.0 with: source: . + targets: ${{ matrix.target }} push: ${{ env.IS_INTERNAL == 'true' }} set: | - *.cache-from=type=gha - *.cache-to=type=gha,mode=max + *.platform=linux/amd64 + *.cache-from=type=gha,scope=${{ matrix.target }} + *.cache-to=type=gha,mode=max,scope=${{ matrix.target }} diff --git a/README.md b/README.md index 7615e14..b8e44bd 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ docker buildx bake --push ### CI(GitHub Actions) - `build.yml` — `master` への push / 週次 / 手動実行で **Docker Hub (`appleple/acms-dev`) へマルチアーキ公開**(provenance / SBOM 添付)。 -- `pr-preview.yml` — Pull Request で **GHCR にプレビューイメージを公開**(`ghcr.io//docker-acms/acms-dev:-`)。フォークからの PR はビルド検証のみ。 +- `pr-preview.yml` — Pull Request で **GHCR にプレビューイメージを公開**(`ghcr.io///acms-dev:-`、amd64・バージョン別 matrix)。フォークからの PR はビルド検証のみ。 - `lint.yml` — `actionlint` によるワークフロー静的検査。 公開には Secrets(`DOCKERHUB_USERNAME` / `DOCKERHUB_TOKEN`)が必要です。 diff --git a/docker-bake.hcl b/docker-bake.hcl index c33c8ed..9cb1dcb 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -74,7 +74,7 @@ target "acms-dev" { labels = { "org.opencontainers.image.title" = "a-blog cms dev runtime (PHP ${php})" - "org.opencontainers.image.source" = "https://github.com/appleple/docker-acms" + "org.opencontainers.image.source" = "https://github.com/appleple/acms-development-docker-images" "org.opencontainers.image.description" = "Apache + PHP ${php} runtime for a-blog cms development (a-blog cms is NOT bundled; mount your project)" } } From 5758413ea12ac7a89cd98e37db6ad8ca4e0fbfa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Fri, 3 Jul 2026 13:30:57 +0900 Subject: [PATCH 17/20] =?UTF-8?q?build.yml=20=E3=82=82=20matrix=20?= =?UTF-8?q?=E4=B8=A6=E5=88=97=E5=8C=96=E3=81=97=E3=80=81CI=20=E3=81=AE?= =?UTF-8?q?=E3=82=B8=E3=83=A7=E3=83=96=E8=A1=A8=E7=A4=BA=E5=90=8D=E3=82=92?= =?UTF-8?q?=E3=83=89=E3=83=83=E3=83=88=E4=BB=98=E3=81=8D=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - build.yml: バージョン別 matrix で並列化(各ジョブが amd64+arm64 を担当)。 対象は docker-bake.hcl から動的取得。 - matrix を {version, target} のペアにし、ジョブ表示名を acms-dev:8.5 の形に (bake のターゲット名は . 不可のため内部的には acms-dev-8-5)。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/build.yml | 34 +++++++++++++++++++++++++++++--- .github/workflows/pr-preview.yml | 17 ++++++++-------- README.md | 2 +- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9b34998..03127f4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,7 @@ # # 必要な Secrets: DOCKERHUB_USERNAME / DOCKERHUB_TOKEN # Actions は commit SHA でピン留め(サプライチェーン対策)。更新は dependabot。 +# PHP バージョンごとに matrix で並列(各ジョブが amd64+arm64 を担当)。 name: Build and publish images on: @@ -28,11 +29,37 @@ concurrency: permissions: {} jobs: + prepare: + name: Resolve build matrix + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + matrix: ${{ steps.gen.outputs.matrix }} + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 + + - name: Resolve targets from docker-bake.hcl + id: gen + run: | + matrix="$(docker buildx bake --print 2>/dev/null | jq -c '{include: [.target | to_entries[] | {version: .value.args.PHP_VERSION, target: .key}]}')" + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" + build: - name: Build PHP images (bake matrix) + name: acms-dev:${{ matrix.version }} + needs: prepare runs-on: ubuntu-latest permissions: contents: read + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} steps: - name: Checkout repository @@ -56,9 +83,10 @@ jobs: uses: docker/bake-action@d3418bd7d0e9324001bca92fa8ba175ea7e6dc9b # v7.3.0 with: source: . + targets: ${{ matrix.target }} push: true set: | - *.cache-from=type=gha - *.cache-to=type=gha,mode=max + *.cache-from=type=gha,scope=${{ matrix.target }} + *.cache-to=type=gha,mode=max,scope=${{ matrix.target }} *.attest=type=provenance,mode=max *.attest=type=sbom diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 0cdff2e..6b06b9b 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -24,13 +24,13 @@ concurrency: permissions: {} jobs: - matrix: + prepare: name: Resolve build matrix runs-on: ubuntu-latest permissions: contents: read outputs: - targets: ${{ steps.gen.outputs.targets }} + matrix: ${{ steps.gen.outputs.matrix }} steps: - name: Checkout repository uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 @@ -40,23 +40,22 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - name: Resolve bake targets from docker-bake.hcl + - name: Resolve targets from docker-bake.hcl id: gen run: | - targets="$(docker buildx bake --print 2>/dev/null | jq -c '[.target | keys[]]')" - echo "targets=$targets" >> "$GITHUB_OUTPUT" + matrix="$(docker buildx bake --print 2>/dev/null | jq -c '{include: [.target | to_entries[] | {version: .value.args.PHP_VERSION, target: .key}]}')" + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" build: - name: ${{ matrix.target }} (amd64) - needs: matrix + name: acms-dev:${{ matrix.version }} (amd64) + needs: prepare runs-on: ubuntu-latest permissions: contents: read packages: write strategy: fail-fast: false - matrix: - target: ${{ fromJson(needs.matrix.outputs.targets) }} + matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} env: # 同一リポジトリの PR のみ GHCR へ push(フォークは検証のみ) IS_INTERNAL: ${{ github.event.pull_request.head.repo.full_name == github.repository }} diff --git a/README.md b/README.md index b8e44bd..8dd9f48 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ docker buildx bake --push ### CI(GitHub Actions) -- `build.yml` — `master` への push / 週次 / 手動実行で **Docker Hub (`appleple/acms-dev`) へマルチアーキ公開**(provenance / SBOM 添付)。 +- `build.yml` — `master` への push / 週次 / 手動実行で **Docker Hub (`appleple/acms-dev`) へマルチアーキ公開**(バージョン別 matrix 並列、provenance / SBOM 添付)。 - `pr-preview.yml` — Pull Request で **GHCR にプレビューイメージを公開**(`ghcr.io///acms-dev:-`、amd64・バージョン別 matrix)。フォークからの PR はビルド検証のみ。 - `lint.yml` — `actionlint` によるワークフロー静的検査。 From 23eaa06e7f3db2f044dcd48d27d8f8f75e3cae64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Fri, 3 Jul 2026 17:01:40 +0900 Subject: [PATCH 18/20] =?UTF-8?q?usermod=20-u=20=E3=81=AB=E3=82=88?= =?UTF-8?q?=E3=82=8B=E3=83=9E=E3=82=A6=E3=83=B3=E3=83=88=E5=85=88=E3=83=97?= =?UTF-8?q?=E3=83=AD=E3=82=B8=E3=82=A7=E3=82=AF=E3=83=88=E3=81=AE=E6=84=8F?= =?UTF-8?q?=E5=9B=B3=E3=81=97=E3=81=AA=E3=81=84=E5=86=8D=E5=B8=B0chown?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 指摘: entrypoint.sh の usermod -o -u "${PUID}" www-data は、www-data の ホームディレクトリが /var/www(README 推奨のマウント先 /var/www/html の 親)であるため、一部の shadow-utils 実装では UID 変更時にホーム配下を 自動で再帰 chown する。マウントしたプロジェクト全体が巻き込まれ得る。 検証: 実機で shadow-utils バージョンごとの挙動を確認したところ、本リポジトリ の対応バージョン中では PHP 7.2(Debian buster, shadow 1:4.5-1.1)でのみ 実際に発生し、/var/www/html 配下のファイルが再帰的に chown されることを 再現した。7.3 以降(bullseye/trixie 系)では発生しない。 対応: Dockerfile で www-data のホームを /nonexistent に切り離す (usermod -d /nonexistent www-data)。entrypoint.sh は変更不要。 DocumentRoot は Apache 設定ファイルで定義され $HOME に依存しないため、 配信・PUID/PGID マッピングへの影響がないことを実機(HTTP 200 応答、 uid/gid 反映)で確認済み。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/settings.json | 9 +++++++++ Dockerfile | 5 +++++ 2 files changed, 14 insertions(+) create mode 100644 .claude/settings.json diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..1dc2b25 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,9 @@ +{ + "permissions": { + "allow": [ + "Bash(git diff *)", + "Read(//private/tmp/**)", + "Bash(docker rmi *)" + ] + } +} diff --git a/Dockerfile b/Dockerfile index 5c54038..9cce505 100644 --- a/Dockerfile +++ b/Dockerfile @@ -73,6 +73,11 @@ RUN set -eux; \ docker-php-ext-enable apcu redis imagick pcov; \ ln -sf /usr/bin/python3 /usr/bin/python; \ a2enmod headers mime expires deflate rewrite ssl; \ + # www-data のホームは既定で /var/www(= APACHE_DOCUMENT_ROOT の親)。 + # 一部の Debian 版(shadow-utils)は usermod -u 実行時にホーム配下を再帰 chown する + # ため、PUID/PGID でマウント済みプロジェクト全体が巻き込まれ得る。 + # ホームを無関係な場所へ切り離し、entrypoint.sh 側は変更せずに無効化する。 + usermod -d /nonexistent www-data; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* From 982f2dee5f087129c184788048f28f568c5f3a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Fri, 3 Jul 2026 17:01:58 +0900 Subject: [PATCH 19/20] =?UTF-8?q?=E3=83=AA=E3=83=9D=E3=82=B8=E3=83=88?= =?UTF-8?q?=E3=83=AA=E3=81=8B=E3=82=89=20.claude/=20=E8=A8=AD=E5=AE=9A?= =?UTF-8?q?=E3=82=92=E9=99=A4=E5=A4=96=EF=BC=88=E8=AA=A4=E3=82=B3=E3=83=9F?= =?UTF-8?q?=E3=83=83=E3=83=88=E3=81=AE=E4=BF=AE=E6=AD=A3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/settings.json | 9 --------- .gitignore | 1 + 2 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 .claude/settings.json diff --git a/.claude/settings.json b/.claude/settings.json deleted file mode 100644 index 1dc2b25..0000000 --- a/.claude/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(git diff *)", - "Read(//private/tmp/**)", - "Bash(docker rmi *)" - ] - } -} diff --git a/.gitignore b/.gitignore index c485a13..2f071c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store docs +.claude/ From d1d842ffef4a1d5d9a932430d1c875959d34cee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E4=BA=95=20=E9=99=B8=E7=99=BB?= Date: Fri, 3 Jul 2026 18:16:09 +0900 Subject: [PATCH 20/20] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=83=AC?= =?UTF-8?q?=E3=83=93=E3=83=A5=E3=83=BC=E6=8C=87=E6=91=9815=E4=BB=B6?= =?UTF-8?q?=E3=81=AB=E5=AF=BE=E5=BF=9C=EF=BC=88CI=E5=A0=85=E7=89=A2?= =?UTF-8?q?=E5=8C=96=E3=83=BBDocumentRoot=E5=86=AA=E7=AD=89=E5=8C=96?= =?UTF-8?q?=E3=83=BBPID1=E5=8C=96=E3=83=BB=E3=83=93=E3=83=AB=E3=83=89?= =?UTF-8?q?=E8=BB=BD=E9=87=8F=E5=8C=96=E3=81=BB=E3=81=8B=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bake失敗の可視化: shell:bash明示・エラー抑制解除・空値チェックを追加 (pipefailで実害はなかったが、エラーメッセージを残すため改善) - lint.yml: reviewdog(github-check)が要求するchecks:write権限を追加 - entrypoint.sh: DocumentRoot反映をinit.txtガード方式から、ビルド時に退避した オリジナル設定(*.orig)からの冪等な再生成方式に変更。再起動のたびに APACHE_DOCUMENT_ROOTの最新値が反映される - 上記sed置換で、値に含まれる sed メタ文字(/ & \)を事前エスケープしクラッシュ ・意図しない展開を防止 - build.yml: concurrency グループのキーを github.sha から github.ref に変更 (push毎に一意なshaでは cancel-in-progress が機能しなかった) - Dockerfile: --no-install-recommends 化で失われていた openssh-client を追加 (git+ssh clone がコンテナ内で失敗する問題を修正) - entrypoint.sh: apache2 を entrypoint プロセスの exec で置き換え、PID1にする。 apache がクラッシュ/OOM-killされた場合にコンテナ自体が終了し、 restart ポリシーで正しく自動復旧できるようになる - README: compose 例から不要な privileged: true を削除 - pr-preview.yml 用に GHCR プレビュータグの自動削除ワークフロー (pr-cleanup.yml) を追加。削除には delete:packages 権限の PAT (GHCR_DELETE_TOKEN) が必要なため、未設定時は警告のみで安全にスキップ - README: pcov.ini がビルド時にイメージへ焼き込まれ、取得済みイメージには 反映されない旨を明記 - docker-bake.hcl: PR プレビュー時に未文書化の latest- タグが 公開されてしまう問題を修正(本番公開時のみ latest を付与) - README: 443番ポートはSSL未設定のため動作しない旨を明記し、compose例から削除 - Dockerfile: 全対応バージョンで静的組込み済みの mbstring の再ビルドと、 docker-php-ext-install が内部で自動実行する enable の重複呼び出しを削除 - Dockerfile: 公式PHPイメージと同じ apt-mark パターンでビルド専用パッケージ (build-essential・*-dev ヘッダ)を除去。自前ビルドした拡張(.so)が実際に リンクする共有ライブラリは ldd で検出し保護(Debian の /lib→/usr/lib symlinkを readlink -f で解決してから dpkg-query に渡す)。 イメージサイズを平均で 250〜350MB 削減 全9バージョン(7.2〜8.5)で再ビルドし、拡張ロード・PID1化・DocumentRoot 冪等性・sed安全性・PUID/PGID・XDEBUGトグル・HEALTHCHECK・CLIツール生存 (git/ssh/python/sendmail等)を実機検証済み。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/build.yml | 10 ++++-- .github/workflows/lint.yml | 1 + .github/workflows/pr-cleanup.yml | 62 ++++++++++++++++++++++++++++++++ .github/workflows/pr-preview.yml | 8 ++++- Dockerfile | 50 +++++++++++++++++++++++--- README.md | 25 +++++++++++-- docker-bake.hcl | 4 ++- entrypoint.sh | 35 +++++++++--------- 8 files changed, 168 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/pr-cleanup.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 03127f4..e52dc22 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ on: - cron: '0 0 * * 0' concurrency: - group: ${{ github.workflow }}-${{ github.sha }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: {} @@ -47,8 +47,14 @@ jobs: - name: Resolve targets from docker-bake.hcl id: gen + shell: bash run: | - matrix="$(docker buildx bake --print 2>/dev/null | jq -c '{include: [.target | to_entries[] | {version: .value.args.PHP_VERSION, target: .key}]}')" + set -euo pipefail + matrix="$(docker buildx bake --print | jq -c '{include: [.target | to_entries[] | {version: .value.args.PHP_VERSION, target: .key}]}')" + if [ -z "$matrix" ] || [ "$matrix" = "null" ]; then + echo "::error::failed to resolve bake targets from docker-bake.hcl" + exit 1 + fi echo "matrix=$matrix" >> "$GITHUB_OUTPUT" build: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 35d91e8..810f763 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,6 +19,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + checks: write steps: - name: Checkout repository uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 diff --git a/.github/workflows/pr-cleanup.yml b/.github/workflows/pr-cleanup.yml new file mode 100644 index 0000000..7c47400 --- /dev/null +++ b/.github/workflows/pr-cleanup.yml @@ -0,0 +1,62 @@ +# PR がクローズ(マージ/却下いずれも)されたら、pr-preview.yml が GHCR に +# 公開したプレビュータグ(acms-dev:-)を削除する。 +# +# 注意: GITHUB_TOKEN では GHCR パッケージの削除ができない +# (GitHub の仕様。delete:packages スコープを持つ PAT が必要)。 +# そのため Secrets に GHCR_DELETE_TOKEN(delete:packages, read:packages)を +# 設定するまでは、このジョブは警告を出して安全にスキップする。 +name: Clean up PR preview images + +on: + pull_request: + types: [closed] + +permissions: {} + +jobs: + cleanup: + name: Delete GHCR preview tags + runs-on: ubuntu-latest + permissions: + contents: read + env: + PR_NUMBER: ${{ github.event.number }} + PACKAGE_NAME: acms-dev + OWNER: ${{ github.repository_owner }} + + steps: + - name: Check for GHCR_DELETE_TOKEN + id: check + shell: bash + run: | + if [ -n "${{ secrets.GHCR_DELETE_TOKEN }}" ]; then + echo "has_token=true" >> "$GITHUB_OUTPUT" + else + echo "has_token=false" >> "$GITHUB_OUTPUT" + echo "::warning::GHCR_DELETE_TOKEN が未設定のため、PR プレビューイメージの自動削除をスキップしました。ghcr.io/${OWNER}//${PACKAGE_NAME} の '-${PR_NUMBER}' サフィックスのタグは手動削除するか、delete:packages 権限を持つ PAT を GHCR_DELETE_TOKEN に設定してください。" + fi + + - name: Delete preview versions + if: steps.check.outputs.has_token == 'true' + shell: bash + env: + GH_TOKEN: ${{ secrets.GHCR_DELETE_TOKEN }} + run: | + set -euo pipefail + suffix="-${PR_NUMBER}" + echo "Package ${PACKAGE_NAME} のバージョンから suffix '${suffix}' を検索します..." + + ids="$(gh api --paginate "/orgs/${OWNER}/packages/container/${PACKAGE_NAME}/versions" \ + | jq -s 'add' \ + | jq -r --arg suffix "$suffix" \ + '.[] | select((.metadata.container.tags // []) | any(endswith($suffix))) | .id')" + + if [ -z "$ids" ]; then + echo "削除対象のタグは見つかりませんでした。" + exit 0 + fi + + echo "$ids" | while read -r id; do + echo "Deleting version id=${id}" + gh api --method DELETE "/orgs/${OWNER}/packages/container/${PACKAGE_NAME}/versions/${id}" + done diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 6b06b9b..6bdb11a 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -42,8 +42,14 @@ jobs: - name: Resolve targets from docker-bake.hcl id: gen + shell: bash run: | - matrix="$(docker buildx bake --print 2>/dev/null | jq -c '{include: [.target | to_entries[] | {version: .value.args.PHP_VERSION, target: .key}]}')" + set -euo pipefail + matrix="$(docker buildx bake --print | jq -c '{include: [.target | to_entries[] | {version: .value.args.PHP_VERSION, target: .key}]}')" + if [ -z "$matrix" ] || [ "$matrix" = "null" ]; then + echo "::error::failed to resolve bake targets from docker-bake.hcl" + exit 1 + fi echo "matrix=$matrix" >> "$GITHUB_OUTPUT" build: diff --git a/Dockerfile b/Dockerfile index 9cce505..ab0bb57 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,6 +19,10 @@ ARG PCOV_VERSION=1.0.12 # - pcov: 既定は pcov.enabled=0(カバレッジ取得時のみ -d pcov.enabled=1) # OPcache は PHP 8.5 で静的組込みのため install せず、未ロード時のみ enable する。 # PHP 7.x 対応のため、apt ソース(archive)・gd フラグ・redis/xdebug の版を分岐する。 +# +# ビルドにしか使わないパッケージ(build-essential・*-dev ヘッダ)は最後に +# apt-mark で洗い出して purge し、開発用途で使う CLI(git・ssh・python 等)と +# 拡張が実行時にリンクする共有ライブラリだけを残す。 RUN set -eux; \ PHP_ID="$(php -r 'echo PHP_VERSION_ID;')"; \ # 旧 Debian(buster/stretch)はアーカイブへ切替(apt-get update を通すため) @@ -29,6 +33,7 @@ RUN set -eux; \ ;; \ esac; \ apt-get update; \ + savedAptMark="$(apt-mark showmanual)"; \ apt-get install -y --no-install-recommends \ libfreetype6-dev \ libmagickwand-dev \ @@ -39,12 +44,15 @@ RUN set -eux; \ libzip-dev \ libonig-dev \ libssl-dev \ + build-essential \ + ; \ + apt-get install -y --no-install-recommends \ jpegoptim \ optipng \ gifsicle \ sendmail \ git-core \ - build-essential \ + openssh-client \ openssl \ python3 \ zip \ @@ -57,8 +65,9 @@ RUN set -eux; \ docker-php-ext-configure gd --with-freetype-dir=/usr --with-jpeg-dir=/usr; \ fi; \ docker-php-ext-install -j"$(nproc)" gd zip; \ - docker-php-ext-install mbstring gettext pdo_mysql mysqli bcmath exif; \ - docker-php-ext-enable mysqli; \ + # mbstring は公式イメージに静的組込み済みのため install しない(全対応バージョンで確認済み) + docker-php-ext-install gettext pdo_mysql mysqli bcmath exif; \ + # docker-php-ext-install は内部で enable まで行うため、個別の enable は不要 php -m | grep -qi 'Zend OPcache' || docker-php-ext-enable opcache; \ # 版依存の pecl 拡張(古い PHP では対応する旧版へフォールバック) REDIS_VER="$REDIS_VERSION"; \ @@ -78,6 +87,33 @@ RUN set -eux; \ # ため、PUID/PGID でマウント済みプロジェクト全体が巻き込まれ得る。 # ホームを無関係な場所へ切り離し、entrypoint.sh 側は変更せずに無効化する。 usermod -d /nonexistent www-data; \ + # ---- ビルド専用パッケージを除去(公式 PHP イメージと同じ apt-mark パターン) ---- + # 1) いったん全パッケージを auto 扱いにし、元々 manual だったもの(ベースイメージ + # 由来)だけ復元する + apt-mark auto '.*' > /dev/null; \ + apt-mark manual $savedAptMark; \ + # 2) 自前ビルドした拡張(.so)が実際にリンクしている共有ライブラリの提供パッケージを + # 検出して manual に固定する(apt はこれらの .so の存在を知らないため、 + # 自動では依存関係として認識されない)。走査対象は拡張の .so のみに絞り、 + # スクリプト等を ldd に渡してノイズが出ないようにする。 + # Debian は /lib が /usr/lib への symlink(usrmerge)なので、ldd が返す + # パスのままでは dpkg-query --search が一致しない。readlink -f で + # symlink(/lib → /usr/lib、バージョンなし .so → 実体)を解決してから渡す。 + find /usr/local/lib/php/extensions -name '*.so' 2>/dev/null \ + | xargs -r -I{} ldd {} 2>/dev/null \ + | grep -E ' => /' \ + | awk '{print $3}' \ + | xargs -r -I{} readlink -f {} \ + | sort -u \ + | xargs -r dpkg-query --search 2>/dev/null \ + | cut -d: -f1 \ + | sort -u \ + | xargs -r apt-mark manual \ + ; \ + # 3) 開発用イメージとして明示的に残したい CLI ツール(ビルド後も使う) + apt-mark manual git openssh-client python3 sendmail jpegoptim optipng gifsicle zip unzip openssl 2>/dev/null || true; \ + # 4) 上記以外(build-essential・*-dev ヘッダ等)を自動判定して除去 + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ apt-get clean; \ rm -rf /var/lib/apt/lists/* @@ -100,7 +136,13 @@ COPY config/pcov.ini /usr/local/etc/php/conf.d/zz-pcov.ini COPY config/xdebug.ini /usr/local/etc/php/xdebug.ini # apache -RUN echo "Mutex posixsem" >> /etc/apache2/apache2.conf +RUN echo "Mutex posixsem" >> /etc/apache2/apache2.conf; \ + # APACHE_DOCUMENT_ROOT の反映を毎回オリジナルから冪等に生成するため退避しておく + # (entrypoint.sh 参照)。2回目以降の起動でも最新の値が反映される。 + cp /etc/apache2/apache2.conf /etc/apache2/apache2.conf.orig; \ + for f in /etc/apache2/sites-available/*.conf /etc/apache2/conf-available/*.conf; do \ + cp "$f" "$f.orig"; \ + done COPY entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/entrypoint.sh diff --git a/README.md b/README.md index 8dd9f48..c9482e6 100644 --- a/README.md +++ b/README.md @@ -34,13 +34,12 @@ services: www: image: appleple/acms-dev:8.3 - privileged: true + restart: always volumes: - ./www:/var/www/html - /etc/localtime:/etc/localtime:ro ports: - "80:80" - - "443:443" depends_on: - mysql environment: @@ -59,6 +58,10 @@ docker compose up > `PUID`/`PGID` を渡すと Apache 実行ユーザ(www-data)の uid/gid をホストに合わせ、 > マウント先に生成されるファイルの所有権ずれ(主に Linux ホスト)を防げます。macOS/Windows では通常不要です。 +> `privileged: true` は不要です(entrypoint の処理は通常の root 権限で完結します)。 +> HTTPS を使う場合は自己署名証明書の作成と `a2ensite default-ssl` の有効化が別途必要です +> (既定では `443` は公開しておらず、SSL 用の vhost も未設定です)。 + ## Xdebug Xdebug はイメージに同梱されており、**専用イメージ(`-xdebug`)は不要**です。 @@ -72,7 +75,12 @@ Xdebug はイメージに同梱されており、**専用イメージ(`-xdebug ```sh docker compose exec www php -d pcov.enabled=1 vendor/bin/phpunit --coverage-text ``` - 設定は [`config/pcov.ini`](config/pcov.ini)。対象を絞る場合は `pcov.directory` を指定。 + 設定は [`config/pcov.ini`](config/pcov.ini) にありますが、これは**ビルド時にイメージへ焼き込まれる**ため、 + 取得済みイメージに対してこのファイルを編集しても反映されません。対象を絞る場合はイメージを再ビルドするか、 + 実行時に `-d` で上書きしてください: + ```sh + docker compose exec www php -d pcov.enabled=1 -d pcov.directory=/var/www/html vendor/bin/phpunit --coverage-text + ``` - **exif** 拡張を同梱しています(EXIF Orientation を使う画像回転処理・テスト向け)。 - カバレッジは PCOV と Xdebug のどちらか一方のみ使用してください(併用は非対応)。 ステップ実行が必要なときだけ `XDEBUG=true`、カバレッジは PCOV が推奨です。 @@ -105,7 +113,18 @@ docker buildx bake --push - `build.yml` — `master` への push / 週次 / 手動実行で **Docker Hub (`appleple/acms-dev`) へマルチアーキ公開**(バージョン別 matrix 並列、provenance / SBOM 添付)。 - `pr-preview.yml` — Pull Request で **GHCR にプレビューイメージを公開**(`ghcr.io///acms-dev:-`、amd64・バージョン別 matrix)。フォークからの PR はビルド検証のみ。 +- `pr-cleanup.yml` — PR クローズ時に GHCR のプレビュータグ(`-`)を削除。 - `lint.yml` — `actionlint` によるワークフロー静的検査。 公開には Secrets(`DOCKERHUB_USERNAME` / `DOCKERHUB_TOKEN`)が必要です。 +PR プレビューのクリーンアップには別途 `GHCR_DELETE_TOKEN`(`delete:packages` / `read:packages` 権限の PAT)が必要です。 +未設定の場合、`pr-cleanup.yml` は削除をスキップし警告を出すだけで失敗はしません。 Actions は commit SHA でピン留めし、`dependabot` が更新 PR を出します。 + +## 可用性について + +`HEALTHCHECK` は Apache への接続可否を検知しますが、**Docker 単体では `unhealthy` を理由に +コンテナを自動再起動しません**(`restart` ポリシーはプロセス終了時のみ発火します)。 +本イメージは Apache をコンテナの PID1 として起動するため、Apache がクラッシュすると +コンテナ自体が終了します。`docker run --restart=always` や compose の `restart: always` を +指定していれば、その時点で正しく自動復旧します。 diff --git a/docker-bake.hcl b/docker-bake.hcl index 9cb1dcb..a2345dc 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -67,9 +67,11 @@ target "acms-dev" { platforms = PLATFORMS + # latest タグは本番公開時(PR_TAG が空)のときだけ付与する。 + # PR プレビューでは未文書化の latest- タグが公開されるのを防ぐ。 tags = concat( ["${REGISTRY}/${IMAGE_NAME}:${php}${PR_TAG}"], - php == PHP_LATEST ? ["${REGISTRY}/${IMAGE_NAME}:latest${PR_TAG}"] : [] + (php == PHP_LATEST && PR_TAG == "") ? ["${REGISTRY}/${IMAGE_NAME}:latest"] : [] ) labels = { diff --git a/entrypoint.sh b/entrypoint.sh index 5d84ff3..f62a88b 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -34,25 +34,28 @@ else echo "[entrypoint] Xdebug: disabled" fi -# document root +# --- DocumentRoot の反映 --- +# 状態ファイルで「初回かどうか」を判定するのではなく、ビルド時に退避した +# オリジナルの設定ファイル(*.orig)から毎回冪等に再生成する。これにより +# 再起動のたびに APACHE_DOCUMENT_ROOT の最新値が確実に反映される。 +# 置換先の値に sed のメタ文字(/ & \)が含まれても壊れないようエスケープする。 echo "${APACHE_DOCUMENT_ROOT}" -INIT_FILE="/var/www/init.txt" - -if test "${APACHE_DOCUMENT_ROOT}" != ""; then - if [ ! -e $INIT_FILE ]; then - sed -ri -e "s!/var/www/html!${APACHE_DOCUMENT_ROOT}!g" /etc/apache2/sites-available/*.conf - sed -ri -e "s!/var/www/!${APACHE_DOCUMENT_ROOT}!g" /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf - touch $INIT_FILE - fi +if [ -n "${APACHE_DOCUMENT_ROOT}" ]; then + esc_root=$(printf '%s' "${APACHE_DOCUMENT_ROOT}" | sed -e 's/[\/&\\]/\\&/g') + for f in /etc/apache2/sites-available/*.conf.orig; do + sed -re "s/\/var\/www\/html/${esc_root}/g" "$f" > "${f%.orig}" + done + for f in /etc/apache2/apache2.conf.orig /etc/apache2/conf-available/*.conf.orig; do + sed -re "s/\/var\/www\//${esc_root}\//g" "$f" > "${f%.orig}" + done fi service sendmail restart -service apache2 restart - -trap 'service apache2 stop; exit 0' TERM -while : -do - sleep 1 -done +# apache2 をこのシェルの exec で置き換え、PID1 にする。 +# こうすることで apache2 がクラッシュ/OOM-killされた場合にコンテナ自体が +# 終了し、docker の restart ポリシー(restart: always 等)で正しく +# 自動復旧できるようになる(バックグラウンド常駐 + sleep ループ方式だと、 +# apache が死んでも PID1 が生き残り「Running」のまま復旧されない)。 +exec /usr/local/bin/apache2-foreground