From 52d65b8ac661b102bdd39fd0ae487b10b48e7eb5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Sep 2026 11:59:57 +0000 Subject: [PATCH 1/8] feat(php-lol): make runtime rootless Co-authored-by: bdossantos <245284+bdossantos@users.noreply.github.com> --- .github/actions/docker/action.yml | 3 +++ dockerfiles/php-lol/.rootless | 0 dockerfiles/php-lol/Dockerfile.8.3 | 8 +++++--- dockerfiles/php-lol/Dockerfile.8.4 | 8 +++++--- dockerfiles/php-lol/Dockerfile.8.5 | 8 +++++--- dockerfiles/php-lol/app.conf | 2 -- dockerfiles/php-lol/nginx.conf | 6 +++--- dockerfiles/php-lol/supervisord.conf | 1 - dockerfiles/php-lol/zzz-php-fpm-tuning.conf | 2 ++ tests/php-lol.yaml | 18 +++++++++++++++--- 10 files changed, 38 insertions(+), 18 deletions(-) create mode 100644 dockerfiles/php-lol/.rootless diff --git a/.github/actions/docker/action.yml b/.github/actions/docker/action.yml index e80e8aea..4237641b 100644 --- a/.github/actions/docker/action.yml +++ b/.github/actions/docker/action.yml @@ -32,6 +32,9 @@ runs: vcs_ref=$(git rev-parse --short HEAD) image_name=$(cd $(dirname ${{ inputs.dockerfile }}) && echo "${PWD##*/}") tags=bdossantos/${image_name}:latest,bdossantos/${image_name}:${version},bdossantos/${image_name}:${version}-${vcs_ref},bdossantos/${image_name}:${version%.*} + if [[ -f "$(dirname ${{ inputs.dockerfile }})/.rootless" ]]; then + tags=${tags},bdossantos/${image_name}:latest-rootless,bdossantos/${image_name}:${version}-rootless,bdossantos/${image_name}:${version%.*}-rootless + fi cache_image=bdossantos/${image_name}:buildcache echo "build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT echo "cache_image=${cache_image}" >> $GITHUB_OUTPUT diff --git a/dockerfiles/php-lol/.rootless b/dockerfiles/php-lol/.rootless new file mode 100644 index 00000000..e69de29b diff --git a/dockerfiles/php-lol/Dockerfile.8.3 b/dockerfiles/php-lol/Dockerfile.8.3 index 7abd3fe9..c4f203ad 100644 --- a/dockerfiles/php-lol/Dockerfile.8.3 +++ b/dockerfiles/php-lol/Dockerfile.8.3 @@ -65,7 +65,7 @@ RUN set -eux \ && curl -L -o /usr/local/bin/pickle https://github.com/FriendsOfPHP/pickle/releases/latest/download/pickle.phar \ && chmod +x /usr/local/bin/pickle \ && mkdir -p /var/lib/php/session \ - && chown -R www-data.www-data /var/lib/php/session \ + && chown -R 65534:65534 /var/lib/php/session \ && pickle install amqp@2.2.0 \ && pickle install --no-interaction apcu@5.1.28 \ && pickle install igbinary@3.2.16 \ @@ -183,7 +183,7 @@ RUN set -eux \ && make \ && make install \ && mkdir -p /var/cache/nginx \ - && chown -R www-data.www-data /var/cache/nginx \ + && chown -R 65534:65534 /var/cache/nginx \ && chsh -s /usr/sbin/nologin www-data \ && apt-get purge -y $BUILD_DEPENDENCIES \ && docker-php-source delete \ @@ -250,7 +250,9 @@ LABEL org.label-schema.build-date="$BUILD_DATE" \ WORKDIR /usr/src/app -EXPOSE 80/tcp 443/tcp +EXPOSE 8080/tcp + +USER 65534:65534 ENTRYPOINT ["/entrypoint.sh"] CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] diff --git a/dockerfiles/php-lol/Dockerfile.8.4 b/dockerfiles/php-lol/Dockerfile.8.4 index 36621d2e..ca148a02 100644 --- a/dockerfiles/php-lol/Dockerfile.8.4 +++ b/dockerfiles/php-lol/Dockerfile.8.4 @@ -65,7 +65,7 @@ RUN set -eux \ && curl -L -o /usr/local/bin/pickle https://github.com/FriendsOfPHP/pickle/releases/latest/download/pickle.phar \ && chmod +x /usr/local/bin/pickle \ && mkdir -p /var/lib/php/session \ - && chown -R www-data.www-data /var/lib/php/session \ + && chown -R 65534:65534 /var/lib/php/session \ && pickle install amqp@2.2.0 \ && pickle install --no-interaction apcu@5.1.28 \ && pickle install igbinary@3.2.16 \ @@ -181,7 +181,7 @@ RUN set -eux \ && make \ && make install \ && mkdir -p /var/cache/nginx \ - && chown -R www-data.www-data /var/cache/nginx \ + && chown -R 65534:65534 /var/cache/nginx \ && chsh -s /usr/sbin/nologin www-data \ && apt-get purge -y $BUILD_DEPENDENCIES \ && docker-php-source delete \ @@ -248,7 +248,9 @@ LABEL org.label-schema.build-date="$BUILD_DATE" \ WORKDIR /usr/src/app -EXPOSE 80/tcp 443/tcp +EXPOSE 8080/tcp + +USER 65534:65534 ENTRYPOINT ["/entrypoint.sh"] CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] diff --git a/dockerfiles/php-lol/Dockerfile.8.5 b/dockerfiles/php-lol/Dockerfile.8.5 index 5a3b1499..8260c01d 100644 --- a/dockerfiles/php-lol/Dockerfile.8.5 +++ b/dockerfiles/php-lol/Dockerfile.8.5 @@ -72,7 +72,7 @@ RUN set -eux \ $BUILD_DEPENDENCIES \ && docker-php-ext-install -j"$(nproc)" zip \ && mkdir -p /var/lib/php/session \ - && chown -R www-data.www-data /var/lib/php/session \ + && chown -R 65534:65534 /var/lib/php/session \ # pickle is incompatible with PHP 8.5 (it bundles Composer 1.x, which is not # compatible with PHP 8.5), so PECL extensions are built from pinned upstream # sources with phpize instead. @@ -247,7 +247,7 @@ RUN set -eux \ && make \ && make install \ && mkdir -p /var/cache/nginx \ - && chown -R www-data.www-data /var/cache/nginx \ + && chown -R 65534:65534 /var/cache/nginx \ && chsh -s /usr/sbin/nologin www-data \ && apt-get purge -y $BUILD_DEPENDENCIES \ && docker-php-source delete \ @@ -314,7 +314,9 @@ LABEL org.label-schema.build-date="$BUILD_DATE" \ WORKDIR /usr/src/app -EXPOSE 80/tcp 443/tcp +EXPOSE 8080/tcp + +USER 65534:65534 ENTRYPOINT ["/entrypoint.sh"] CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] diff --git a/dockerfiles/php-lol/app.conf b/dockerfiles/php-lol/app.conf index 0e136dd2..8de82670 100644 --- a/dockerfiles/php-lol/app.conf +++ b/dockerfiles/php-lol/app.conf @@ -3,7 +3,6 @@ command = /usr/local/sbin/php-fpm -F -y /usr/local/etc/php-fpm.conf stdout_logfile = /dev/stdout stdout_logfile_maxbytes = 0 redirect_stderr = true -user = root autostart = true autorestart = true priority = 5 @@ -13,7 +12,6 @@ command = /usr/sbin/nginx -g "daemon off;" stdout_logfile = /dev/stdout stdout_logfile_maxbytes = 0 redirect_stderr = true -user = root autostart = true autorestart = true priority = 10 diff --git a/dockerfiles/php-lol/nginx.conf b/dockerfiles/php-lol/nginx.conf index ba196c43..cd931d20 100644 --- a/dockerfiles/php-lol/nginx.conf +++ b/dockerfiles/php-lol/nginx.conf @@ -1,4 +1,4 @@ -user www-data www-data; +# Rootless nginx runs as the container user. pid /dev/shm/nginx.pid; @@ -76,8 +76,8 @@ http { open_file_cache_errors on; server { - listen [::]:80 default_server; - listen 80 default_server; + listen [::]:8080 default_server; + listen 8080 default_server; # PHP fpm status location ~ ^/(php-fpm-status|php-fpm-ping)$ { diff --git a/dockerfiles/php-lol/supervisord.conf b/dockerfiles/php-lol/supervisord.conf index c72ea901..cb08ece2 100644 --- a/dockerfiles/php-lol/supervisord.conf +++ b/dockerfiles/php-lol/supervisord.conf @@ -9,7 +9,6 @@ logfile_maxbytes = 0 loglevel = error nodaemon = true pidfile = /dev/shm/supervisord.pid -user = root [supervisorctl] serverurl=unix:///dev/shm/supervisord.sock diff --git a/dockerfiles/php-lol/zzz-php-fpm-tuning.conf b/dockerfiles/php-lol/zzz-php-fpm-tuning.conf index a79eb83f..a926111c 100644 --- a/dockerfiles/php-lol/zzz-php-fpm-tuning.conf +++ b/dockerfiles/php-lol/zzz-php-fpm-tuning.conf @@ -4,6 +4,8 @@ log_level = warning pid = /dev/shm/php-fpm.pid [www] +user = nobody +group = nogroup access.log = /dev/null catch_workers_output = yes clear_env = no diff --git a/tests/php-lol.yaml b/tests/php-lol.yaml index ebc07774..6849651c 100644 --- a/tests/php-lol.yaml +++ b/tests/php-lol.yaml @@ -124,7 +124,7 @@ commandTests: command: 'sha256sum' args: ['/etc/nginx/nginx.conf'] expectedOutput: - - '0c21ca2a7522fee98b6d5a0f28e0f6b1840d3df4d23b0b182b5c45c9d8b5ff8f' + - '643f26a37d80bd94b983ab46f80b14b78ede41e3bee12be79a7b4ebebd43e426' - name: 'nginx mime.types checksum' command: 'sha256sum' @@ -136,13 +136,25 @@ commandTests: command: 'sha256sum' args: ['/etc/supervisor/supervisord.conf'] expectedOutput: - - 'cbf3f7370b1fd9f24360c20cc9e909f3298635d456fa76d97f531af0136a390c' + - '7c1b6af616372d69f9beb279834b4b9bab0deb31ed454a21193b563817bf9304' - name: 'supervisor app.conf checksum' command: 'sha256sum' args: ['/etc/supervisor/conf.d/app.conf'] expectedOutput: - - 'bbdd21d87a9b30770de6b434673caf6594eb67bc4ff5c124f8c0ccb453c62d6b' + - 'ffaca82839725c81b62f59a5da6fc941f2643eee5e649654725e01c80b28b1b4' + + - name: 'default user uid is nobody' + command: 'id' + args: ['-u'] + exitCode: 0 + expectedOutput: ['65534'] + + - name: 'default user gid is nogroup' + command: 'id' + args: ['-g'] + exitCode: 0 + expectedOutput: ['65534'] - name: 'php-fpm config test' command: '/usr/local/sbin/php-fpm' From ebf1349682147de3990e05e078f7e6ba8a874cec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:01:31 +0000 Subject: [PATCH 2/8] test(php-lol): cover rootless runtime Co-authored-by: bdossantos <245284+bdossantos@users.noreply.github.com> --- README.md | 2 +- tests/php-lol.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 46f8ff82..77533fa8 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ multi-stage builds, pinned dependencies, and non-root users. | [dnscrypt-proxy](dockerfiles/dnscrypt-proxy) | [DNSCrypt](https://dnscrypt.info/) proxy with encrypted DNS support | | [memcached](dockerfiles/memcached) | [Memcached](https://memcached.org/) with built-in proxy support and embedded [routelib](https://github.com/memcached/memcached-proxylibs) | | [paperless-ngx](dockerfiles/paperless-ngx) | [Paperless-ngx](https://docs.paperless-ngx.com/) document management system | -| [php-lol](dockerfiles/php-lol) | PHP-FPM with Nginx and common extensions (8.3, 8.4, 8.5) | +| [php-lol](dockerfiles/php-lol) | PHP-FPM with Nginx and common extensions (8.3, 8.4, 8.5, plus `-rootless` tags) | | [pingdom-exporter](dockerfiles/pingdom-exporter) | Prometheus exporter for Pingdom metrics | | [pint](dockerfiles/pint) | [Pint](https://cloudflare.github.io/pint/) – Prometheus rule linter by Cloudflare | | [python-github-backup](dockerfiles/python-github-backup) | [python-github-backup](https://github.com/josegonzalez/python-github-backup) – GitHub repository backup tool | diff --git a/tests/php-lol.yaml b/tests/php-lol.yaml index 6849651c..5ea63196 100644 --- a/tests/php-lol.yaml +++ b/tests/php-lol.yaml @@ -112,7 +112,7 @@ commandTests: command: 'sha256sum' args: ['/usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf'] expectedOutput: - - 'e3772ca736903a1a4c27a715adae6c2ef35059119b527cefb30bac50af94ffef' + - '0d66730a9658f8c8553e73878b214a5c96084248a406660f593299f8dc8940ab' - name: 'php hardening config checksum' command: 'sha256sum' From 9b43632410114c4a754002c1c15888139c2f4114 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:01:59 +0000 Subject: [PATCH 3/8] fix(ci): avoid clobbering rootless php-lol tags Co-authored-by: bdossantos <245284+bdossantos@users.noreply.github.com> --- .github/actions/docker/action.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/docker/action.yml b/.github/actions/docker/action.yml index 4237641b..3c087b28 100644 --- a/.github/actions/docker/action.yml +++ b/.github/actions/docker/action.yml @@ -33,7 +33,7 @@ runs: image_name=$(cd $(dirname ${{ inputs.dockerfile }}) && echo "${PWD##*/}") tags=bdossantos/${image_name}:latest,bdossantos/${image_name}:${version},bdossantos/${image_name}:${version}-${vcs_ref},bdossantos/${image_name}:${version%.*} if [[ -f "$(dirname ${{ inputs.dockerfile }})/.rootless" ]]; then - tags=${tags},bdossantos/${image_name}:latest-rootless,bdossantos/${image_name}:${version}-rootless,bdossantos/${image_name}:${version%.*}-rootless + tags=${tags},bdossantos/${image_name}:${version}-rootless,bdossantos/${image_name}:${version%.*}-rootless fi cache_image=bdossantos/${image_name}:buildcache echo "build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT diff --git a/README.md b/README.md index 77533fa8..2e8f22d0 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ multi-stage builds, pinned dependencies, and non-root users. | [dnscrypt-proxy](dockerfiles/dnscrypt-proxy) | [DNSCrypt](https://dnscrypt.info/) proxy with encrypted DNS support | | [memcached](dockerfiles/memcached) | [Memcached](https://memcached.org/) with built-in proxy support and embedded [routelib](https://github.com/memcached/memcached-proxylibs) | | [paperless-ngx](dockerfiles/paperless-ngx) | [Paperless-ngx](https://docs.paperless-ngx.com/) document management system | -| [php-lol](dockerfiles/php-lol) | PHP-FPM with Nginx and common extensions (8.3, 8.4, 8.5, plus `-rootless` tags) | +| [php-lol](dockerfiles/php-lol) | PHP-FPM with Nginx and common extensions (8.3, 8.4, 8.5, plus versioned `-rootless` tags) | | [pingdom-exporter](dockerfiles/pingdom-exporter) | Prometheus exporter for Pingdom metrics | | [pint](dockerfiles/pint) | [Pint](https://cloudflare.github.io/pint/) – Prometheus rule linter by Cloudflare | | [python-github-backup](dockerfiles/python-github-backup) | [python-github-backup](https://github.com/josegonzalez/python-github-backup) – GitHub repository backup tool | From a9fbccf29f5bf010926efe9895a435ea3e836092 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:09:12 +0000 Subject: [PATCH 4/8] feat(php-lol): add dedicated rootless variants Co-authored-by: bdossantos <245284+bdossantos@users.noreply.github.com> --- .github/actions/docker/action.yml | 23 +- Makefile | 7 +- docker-compose.ci.yml | 30 +- dockerfiles/php-lol/Dockerfile.8.3 | 49 ++- dockerfiles/php-lol/Dockerfile.8.4 | 49 ++- dockerfiles/php-lol/Dockerfile.8.5 | 49 ++- dockerfiles/php-lol/app.conf | 2 + dockerfiles/php-lol/app.rootless.conf | 17 + dockerfiles/php-lol/nginx.conf | 6 +- dockerfiles/php-lol/nginx.rootless.conf | 105 ++++++ dockerfiles/php-lol/supervisord.conf | 1 + dockerfiles/php-lol/supervisord.rootless.conf | 20 + dockerfiles/php-lol/zzz-php-fpm-tuning.conf | 2 - .../php-lol/zzz-php-fpm-tuning.rootless.conf | 22 ++ tests/php-lol-rootless.yaml | 344 ++++++++++++++++++ tests/php-lol.yaml | 20 +- 16 files changed, 714 insertions(+), 32 deletions(-) create mode 100644 dockerfiles/php-lol/app.rootless.conf create mode 100644 dockerfiles/php-lol/nginx.rootless.conf create mode 100644 dockerfiles/php-lol/supervisord.rootless.conf create mode 100644 dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf create mode 100644 tests/php-lol-rootless.yaml diff --git a/.github/actions/docker/action.yml b/.github/actions/docker/action.yml index 3c087b28..27ef69b7 100644 --- a/.github/actions/docker/action.yml +++ b/.github/actions/docker/action.yml @@ -31,14 +31,19 @@ runs: version=$(grep -E '^\s*(ENV\s+)?VERSION=' '${{ inputs.dockerfile }}' | tail -1 | sed -E 's/^.*VERSION=([^ \\]+).*/\1/') vcs_ref=$(git rev-parse --short HEAD) image_name=$(cd $(dirname ${{ inputs.dockerfile }}) && echo "${PWD##*/}") + rootless=false + rootless_tags= tags=bdossantos/${image_name}:latest,bdossantos/${image_name}:${version},bdossantos/${image_name}:${version}-${vcs_ref},bdossantos/${image_name}:${version%.*} if [[ -f "$(dirname ${{ inputs.dockerfile }})/.rootless" ]]; then - tags=${tags},bdossantos/${image_name}:${version}-rootless,bdossantos/${image_name}:${version%.*}-rootless + rootless=true + rootless_tags=bdossantos/${image_name}:${version}-rootless,bdossantos/${image_name}:${version%.*}-rootless fi cache_image=bdossantos/${image_name}:buildcache echo "build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT echo "cache_image=${cache_image}" >> $GITHUB_OUTPUT echo "path=$(dirname ${{ inputs.dockerfile }})" >> $GITHUB_OUTPUT + echo "rootless=${rootless}" >> $GITHUB_OUTPUT + echo "rootless_tags=${rootless_tags}" >> $GITHUB_OUTPUT echo "tags=${tags}" >> $GITHUB_OUTPUT echo "vcs_ref=${vcs_ref}" >> $GITHUB_OUTPUT @@ -55,3 +60,19 @@ runs: push: ${{ github.event_name != 'pull_request' }} sbom: true tags: ${{ steps.context.outputs.tags }} + + - name: Build and push rootless docker image + if: steps.context.outputs.rootless == 'true' + uses: docker/build-push-action@v6 + with: + build-args: | + BUILD_DATE=${{ steps.context.outputs.build_date }} + VCS_REF=${{ steps.context.outputs.vcs_ref }} + cache-from: type=registry,ref=${{ steps.context.outputs.cache_image }} + cache-to: type=registry,ref=${{ steps.context.outputs.cache_image }},mode=max + context: ${{ steps.context.outputs.path }} + file: ${{ inputs.dockerfile }} + push: ${{ github.event_name != 'pull_request' }} + sbom: true + tags: ${{ steps.context.outputs.rootless_tags }} + target: run-rootless diff --git a/Makefile b/Makefile index 4eb96b13..03b6ce93 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,12 @@ container-structure-test: ## Run container-structure-test $(info --> Run container-structure-test) @$(CWD)/bin/container-structure-test test --image bdossantos/dnscrypt-proxy --config tests/dnscrypt-proxy.yaml @$(CWD)/bin/container-structure-test test --image bdossantos/paperless-ngx --config tests/paperless-ngx.yaml - @$(CWD)/bin/container-structure-test test --image bdossantos/php-lol --config tests/php-lol.yaml + @$(CWD)/bin/container-structure-test test --image bdossantos/php-lol83 --config tests/php-lol.yaml + @$(CWD)/bin/container-structure-test test --image bdossantos/php-lol84 --config tests/php-lol.yaml + @$(CWD)/bin/container-structure-test test --image bdossantos/php-lol85 --config tests/php-lol.yaml + @$(CWD)/bin/container-structure-test test --image bdossantos/php-lol83-rootless --config tests/php-lol-rootless.yaml + @$(CWD)/bin/container-structure-test test --image bdossantos/php-lol84-rootless --config tests/php-lol-rootless.yaml + @$(CWD)/bin/container-structure-test test --image bdossantos/php-lol85-rootless --config tests/php-lol-rootless.yaml @$(CWD)/bin/container-structure-test test --image bdossantos/pint --config tests/pint.yaml @$(CWD)/bin/container-structure-test test --image bdossantos/python-github-backup --config tests/python-github-backup.yaml @$(CWD)/bin/container-structure-test test --image bdossantos/radicale --config tests/radicale.yaml diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml index bef51ba7..819225f8 100644 --- a/docker-compose.ci.yml +++ b/docker-compose.ci.yml @@ -21,22 +21,46 @@ services: build: context: dockerfiles/php-lol dockerfile: Dockerfile.8.3 - image: bdossantos/php-lol + image: bdossantos/php-lol83 container_name: php-lol83 php-lol84: <<: *default build: context: dockerfiles/php-lol dockerfile: Dockerfile.8.4 - image: bdossantos/php-lol + image: bdossantos/php-lol84 container_name: php-lol84 php-lol85: <<: *default build: context: dockerfiles/php-lol dockerfile: Dockerfile.8.5 - image: bdossantos/php-lol + image: bdossantos/php-lol85 container_name: php-lol85 + php-lol83-rootless: + <<: *default + build: + context: dockerfiles/php-lol + dockerfile: Dockerfile.8.3 + target: run-rootless + image: bdossantos/php-lol83-rootless + container_name: php-lol83-rootless + php-lol84-rootless: + <<: *default + build: + context: dockerfiles/php-lol + dockerfile: Dockerfile.8.4 + target: run-rootless + image: bdossantos/php-lol84-rootless + container_name: php-lol84-rootless + php-lol85-rootless: + <<: *default + build: + context: dockerfiles/php-lol + dockerfile: Dockerfile.8.5 + target: run-rootless + image: bdossantos/php-lol85-rootless + container_name: php-lol85-rootless pingdom-exporter: <<: *default build: diff --git a/dockerfiles/php-lol/Dockerfile.8.3 b/dockerfiles/php-lol/Dockerfile.8.3 index c4f203ad..10a6d5cc 100644 --- a/dockerfiles/php-lol/Dockerfile.8.3 +++ b/dockerfiles/php-lol/Dockerfile.8.3 @@ -65,7 +65,7 @@ RUN set -eux \ && curl -L -o /usr/local/bin/pickle https://github.com/FriendsOfPHP/pickle/releases/latest/download/pickle.phar \ && chmod +x /usr/local/bin/pickle \ && mkdir -p /var/lib/php/session \ - && chown -R 65534:65534 /var/lib/php/session \ + && chown -R www-data.www-data /var/lib/php/session \ && pickle install amqp@2.2.0 \ && pickle install --no-interaction apcu@5.1.28 \ && pickle install igbinary@3.2.16 \ @@ -183,7 +183,7 @@ RUN set -eux \ && make \ && make install \ && mkdir -p /var/cache/nginx \ - && chown -R 65534:65534 /var/cache/nginx \ + && chown -R www-data.www-data /var/cache/nginx \ && chsh -s /usr/sbin/nologin www-data \ && apt-get purge -y $BUILD_DEPENDENCIES \ && docker-php-source delete \ @@ -250,6 +250,51 @@ LABEL org.label-schema.build-date="$BUILD_DATE" \ WORKDIR /usr/src/app +EXPOSE 80/tcp 443/tcp + +ENTRYPOINT ["/entrypoint.sh"] +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] + +FROM foundation AS run-rootless + +ARG BUILD_DATE +ARG VCS_REF +ARG VERSION=8.3.33 + +LABEL org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.name="php-lol" \ + org.label-schema.schema-version="1.0" \ + org.label-schema.url="https://github.com/bdossantos/dockerfiles" \ + org.label-schema.usage="https://github.com/bdossantos/dockerfiles" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/bdossantos/dockerfiles" \ + org.label-schema.vendor="PHP" \ + org.label-schema.version="$VERSION" \ + org.opencontainers.image.created="$BUILD_DATE" \ + org.opencontainers.image.documentation="https://github.com/bdossantos/dockerfiles" \ + org.opencontainers.image.revision="$VCS_REF" \ + org.opencontainers.image.source="https://github.com/bdossantos/dockerfiles" \ + org.opencontainers.image.title="php-lol" \ + org.opencontainers.image.url="https://github.com/bdossantos/dockerfiles" \ + org.opencontainers.image.vendor="PHP" \ + org.opencontainers.image.version="$VERSION" + +COPY app.rootless.conf /etc/supervisor/conf.d/app.conf +COPY nginx.rootless.conf /etc/nginx/nginx.conf +COPY supervisord.rootless.conf /etc/supervisor/supervisord.conf +COPY zzz-php-fpm-tuning.rootless.conf /usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf + +RUN chown -R 65534:65534 \ + /var/cache/nginx \ + /var/lib/php/session \ + && chmod 0444 \ + /etc/nginx/nginx.conf \ + /etc/supervisor/conf.d/app.conf \ + /etc/supervisor/supervisord.conf \ + /usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf + +WORKDIR /usr/src/app + EXPOSE 8080/tcp USER 65534:65534 diff --git a/dockerfiles/php-lol/Dockerfile.8.4 b/dockerfiles/php-lol/Dockerfile.8.4 index ca148a02..4b65e2eb 100644 --- a/dockerfiles/php-lol/Dockerfile.8.4 +++ b/dockerfiles/php-lol/Dockerfile.8.4 @@ -65,7 +65,7 @@ RUN set -eux \ && curl -L -o /usr/local/bin/pickle https://github.com/FriendsOfPHP/pickle/releases/latest/download/pickle.phar \ && chmod +x /usr/local/bin/pickle \ && mkdir -p /var/lib/php/session \ - && chown -R 65534:65534 /var/lib/php/session \ + && chown -R www-data.www-data /var/lib/php/session \ && pickle install amqp@2.2.0 \ && pickle install --no-interaction apcu@5.1.28 \ && pickle install igbinary@3.2.16 \ @@ -181,7 +181,7 @@ RUN set -eux \ && make \ && make install \ && mkdir -p /var/cache/nginx \ - && chown -R 65534:65534 /var/cache/nginx \ + && chown -R www-data.www-data /var/cache/nginx \ && chsh -s /usr/sbin/nologin www-data \ && apt-get purge -y $BUILD_DEPENDENCIES \ && docker-php-source delete \ @@ -248,6 +248,51 @@ LABEL org.label-schema.build-date="$BUILD_DATE" \ WORKDIR /usr/src/app +EXPOSE 80/tcp 443/tcp + +ENTRYPOINT ["/entrypoint.sh"] +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] + +FROM foundation AS run-rootless + +ARG BUILD_DATE +ARG VCS_REF +ARG VERSION=8.4.25 + +LABEL org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.name="php-lol" \ + org.label-schema.schema-version="1.0" \ + org.label-schema.url="https://github.com/bdossantos/dockerfiles" \ + org.label-schema.usage="https://github.com/bdossantos/dockerfiles" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/bdossantos/dockerfiles" \ + org.label-schema.vendor="PHP" \ + org.label-schema.version="$VERSION" \ + org.opencontainers.image.created="$BUILD_DATE" \ + org.opencontainers.image.documentation="https://github.com/bdossantos/dockerfiles" \ + org.opencontainers.image.revision="$VCS_REF" \ + org.opencontainers.image.source="https://github.com/bdossantos/dockerfiles" \ + org.opencontainers.image.title="php-lol" \ + org.opencontainers.image.url="https://github.com/bdossantos/dockerfiles" \ + org.opencontainers.image.vendor="PHP" \ + org.opencontainers.image.version="$VERSION" + +COPY app.rootless.conf /etc/supervisor/conf.d/app.conf +COPY nginx.rootless.conf /etc/nginx/nginx.conf +COPY supervisord.rootless.conf /etc/supervisor/supervisord.conf +COPY zzz-php-fpm-tuning.rootless.conf /usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf + +RUN chown -R 65534:65534 \ + /var/cache/nginx \ + /var/lib/php/session \ + && chmod 0444 \ + /etc/nginx/nginx.conf \ + /etc/supervisor/conf.d/app.conf \ + /etc/supervisor/supervisord.conf \ + /usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf + +WORKDIR /usr/src/app + EXPOSE 8080/tcp USER 65534:65534 diff --git a/dockerfiles/php-lol/Dockerfile.8.5 b/dockerfiles/php-lol/Dockerfile.8.5 index 8260c01d..25303b24 100644 --- a/dockerfiles/php-lol/Dockerfile.8.5 +++ b/dockerfiles/php-lol/Dockerfile.8.5 @@ -72,7 +72,7 @@ RUN set -eux \ $BUILD_DEPENDENCIES \ && docker-php-ext-install -j"$(nproc)" zip \ && mkdir -p /var/lib/php/session \ - && chown -R 65534:65534 /var/lib/php/session \ + && chown -R www-data.www-data /var/lib/php/session \ # pickle is incompatible with PHP 8.5 (it bundles Composer 1.x, which is not # compatible with PHP 8.5), so PECL extensions are built from pinned upstream # sources with phpize instead. @@ -247,7 +247,7 @@ RUN set -eux \ && make \ && make install \ && mkdir -p /var/cache/nginx \ - && chown -R 65534:65534 /var/cache/nginx \ + && chown -R www-data.www-data /var/cache/nginx \ && chsh -s /usr/sbin/nologin www-data \ && apt-get purge -y $BUILD_DEPENDENCIES \ && docker-php-source delete \ @@ -314,6 +314,51 @@ LABEL org.label-schema.build-date="$BUILD_DATE" \ WORKDIR /usr/src/app +EXPOSE 80/tcp 443/tcp + +ENTRYPOINT ["/entrypoint.sh"] +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] + +FROM foundation AS run-rootless + +ARG BUILD_DATE +ARG VCS_REF +ARG VERSION=8.5.10 + +LABEL org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.name="php-lol" \ + org.label-schema.schema-version="1.0" \ + org.label-schema.url="https://github.com/bdossantos/dockerfiles" \ + org.label-schema.usage="https://github.com/bdossantos/dockerfiles" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/bdossantos/dockerfiles" \ + org.label-schema.vendor="PHP" \ + org.label-schema.version="$VERSION" \ + org.opencontainers.image.created="$BUILD_DATE" \ + org.opencontainers.image.documentation="https://github.com/bdossantos/dockerfiles" \ + org.opencontainers.image.revision="$VCS_REF" \ + org.opencontainers.image.source="https://github.com/bdossantos/dockerfiles" \ + org.opencontainers.image.title="php-lol" \ + org.opencontainers.image.url="https://github.com/bdossantos/dockerfiles" \ + org.opencontainers.image.vendor="PHP" \ + org.opencontainers.image.version="$VERSION" + +COPY app.rootless.conf /etc/supervisor/conf.d/app.conf +COPY nginx.rootless.conf /etc/nginx/nginx.conf +COPY supervisord.rootless.conf /etc/supervisor/supervisord.conf +COPY zzz-php-fpm-tuning.rootless.conf /usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf + +RUN chown -R 65534:65534 \ + /var/cache/nginx \ + /var/lib/php/session \ + && chmod 0444 \ + /etc/nginx/nginx.conf \ + /etc/supervisor/conf.d/app.conf \ + /etc/supervisor/supervisord.conf \ + /usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf + +WORKDIR /usr/src/app + EXPOSE 8080/tcp USER 65534:65534 diff --git a/dockerfiles/php-lol/app.conf b/dockerfiles/php-lol/app.conf index 8de82670..0e136dd2 100644 --- a/dockerfiles/php-lol/app.conf +++ b/dockerfiles/php-lol/app.conf @@ -3,6 +3,7 @@ command = /usr/local/sbin/php-fpm -F -y /usr/local/etc/php-fpm.conf stdout_logfile = /dev/stdout stdout_logfile_maxbytes = 0 redirect_stderr = true +user = root autostart = true autorestart = true priority = 5 @@ -12,6 +13,7 @@ command = /usr/sbin/nginx -g "daemon off;" stdout_logfile = /dev/stdout stdout_logfile_maxbytes = 0 redirect_stderr = true +user = root autostart = true autorestart = true priority = 10 diff --git a/dockerfiles/php-lol/app.rootless.conf b/dockerfiles/php-lol/app.rootless.conf new file mode 100644 index 00000000..8de82670 --- /dev/null +++ b/dockerfiles/php-lol/app.rootless.conf @@ -0,0 +1,17 @@ +[program:php-fpm] +command = /usr/local/sbin/php-fpm -F -y /usr/local/etc/php-fpm.conf +stdout_logfile = /dev/stdout +stdout_logfile_maxbytes = 0 +redirect_stderr = true +autostart = true +autorestart = true +priority = 5 + +[program:nginx] +command = /usr/sbin/nginx -g "daemon off;" +stdout_logfile = /dev/stdout +stdout_logfile_maxbytes = 0 +redirect_stderr = true +autostart = true +autorestart = true +priority = 10 diff --git a/dockerfiles/php-lol/nginx.conf b/dockerfiles/php-lol/nginx.conf index cd931d20..ba196c43 100644 --- a/dockerfiles/php-lol/nginx.conf +++ b/dockerfiles/php-lol/nginx.conf @@ -1,4 +1,4 @@ -# Rootless nginx runs as the container user. +user www-data www-data; pid /dev/shm/nginx.pid; @@ -76,8 +76,8 @@ http { open_file_cache_errors on; server { - listen [::]:8080 default_server; - listen 8080 default_server; + listen [::]:80 default_server; + listen 80 default_server; # PHP fpm status location ~ ^/(php-fpm-status|php-fpm-ping)$ { diff --git a/dockerfiles/php-lol/nginx.rootless.conf b/dockerfiles/php-lol/nginx.rootless.conf new file mode 100644 index 00000000..28ae2ccf --- /dev/null +++ b/dockerfiles/php-lol/nginx.rootless.conf @@ -0,0 +1,105 @@ +pid /dev/shm/nginx.pid; + +worker_processes auto; +worker_rlimit_nofile 8192; + +events { + worker_connections 8000; +} + +http { + server_tokens off; + + root /etc/nginx/html; + + include /etc/nginx/mime.types; + + default_type application/octet-stream; + + charset_types + text/css + text/plain + text/vnd.wap.wml + application/javascript + application/json + application/rss+xml + application/xml; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /dev/stdout main; + error_log /dev/stderr error; + + keepalive_timeout 20s; + + sendfile on; + tcp_nopush on; + + gzip on; + gzip_comp_level 5; + gzip_min_length 256; + gzip_proxied any; + gzip_vary on; + gzip_types + application/atom+xml + application/javascript + application/json + application/ld+json + application/manifest+json + application/rss+xml + application/vnd.geo+json + application/vnd.ms-fontobject + application/x-font-ttf + application/x-web-app-manifest+json + application/xhtml+xml + application/xml + font/opentype + image/bmp + image/svg+xml + image/x-icon + text/cache-manifest + text/css + text/plain + text/vcard + text/vnd.rim.location.xloc + text/vtt + text/x-component + text/x-cross-domain-policy; + + open_file_cache max=1000 inactive=20s; + open_file_cache_valid 30s; + open_file_cache_min_uses 2; + open_file_cache_errors on; + + server { + listen [::]:8080 default_server; + listen 8080 default_server; + + # PHP fpm status + location ~ ^/(php-fpm-status|php-fpm-ping)$ { + include /etc/nginx/fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_pass 127.0.0.1:9000; + allow 10.0.0.0/8; + allow 127.0.0.1; + allow 172.16.0.0/12; + allow 192.168.0.0/16; + deny all; + } + + # Stats + location ~ ^/(nginx_status|stub_status)$ { + stub_status on; + access_log off; + allow 10.0.0.0/8; + allow 127.0.0.1; + allow 172.16.0.0/12; + allow 192.168.0.0/16; + deny all; + } + } + + include /etc/nginx/conf.d/*; +} diff --git a/dockerfiles/php-lol/supervisord.conf b/dockerfiles/php-lol/supervisord.conf index cb08ece2..c72ea901 100644 --- a/dockerfiles/php-lol/supervisord.conf +++ b/dockerfiles/php-lol/supervisord.conf @@ -9,6 +9,7 @@ logfile_maxbytes = 0 loglevel = error nodaemon = true pidfile = /dev/shm/supervisord.pid +user = root [supervisorctl] serverurl=unix:///dev/shm/supervisord.sock diff --git a/dockerfiles/php-lol/supervisord.rootless.conf b/dockerfiles/php-lol/supervisord.rootless.conf new file mode 100644 index 00000000..cb08ece2 --- /dev/null +++ b/dockerfiles/php-lol/supervisord.rootless.conf @@ -0,0 +1,20 @@ +[unix_http_server] +chmod = 0700 +chown = nobody:nogroup +file = /dev/shm/supervisord.sock + +[supervisord] +logfile = /dev/stdout +logfile_maxbytes = 0 +loglevel = error +nodaemon = true +pidfile = /dev/shm/supervisord.pid + +[supervisorctl] +serverurl=unix:///dev/shm/supervisord.sock + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[include] +files = /etc/supervisor/conf.d/*.conf diff --git a/dockerfiles/php-lol/zzz-php-fpm-tuning.conf b/dockerfiles/php-lol/zzz-php-fpm-tuning.conf index a926111c..a79eb83f 100644 --- a/dockerfiles/php-lol/zzz-php-fpm-tuning.conf +++ b/dockerfiles/php-lol/zzz-php-fpm-tuning.conf @@ -4,8 +4,6 @@ log_level = warning pid = /dev/shm/php-fpm.pid [www] -user = nobody -group = nogroup access.log = /dev/null catch_workers_output = yes clear_env = no diff --git a/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf b/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf new file mode 100644 index 00000000..a926111c --- /dev/null +++ b/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf @@ -0,0 +1,22 @@ +[global] +error_log = /proc/self/fd/2 +log_level = warning +pid = /dev/shm/php-fpm.pid + +[www] +user = nobody +group = nogroup +access.log = /dev/null +catch_workers_output = yes +clear_env = no +listen.backlog = 65535 +ping.path = /php-fpm-ping +ping.response = pong +pm = static +pm.max_children = 64 +pm.max_requests = 1024 +pm.max_spare_servers = 64 +pm.process_idle_timeout = 10s +pm.start_servers = 16 +pm.status_path = /php-fpm-status +rlimit_files = 65535 diff --git a/tests/php-lol-rootless.yaml b/tests/php-lol-rootless.yaml new file mode 100644 index 00000000..5ce4e322 --- /dev/null +++ b/tests/php-lol-rootless.yaml @@ -0,0 +1,344 @@ +schemaVersion: '2.0.0' + +fileExistenceTests: + - name: 'nginx binary exists' + path: '/usr/sbin/nginx' + shouldExist: true + permissions: '-rwxr-xr-x' + uid: 0 + gid: 0 + + - name: 'php binary exists' + path: '/usr/local/bin/php' + shouldExist: true + permissions: '-rwxr-xr-x' + uid: 0 + gid: 0 + + - name: 'php-fpm binary exists' + path: '/usr/local/sbin/php-fpm' + shouldExist: true + permissions: '-rwxr-xr-x' + uid: 0 + gid: 0 + + - name: 'php.ini exists' + path: '/usr/local/etc/php/php.ini' + shouldExist: true + permissions: '-r--r--r--' + uid: 0 + gid: 0 + + - name: 'apcu config exists' + path: '/usr/local/etc/php/conf.d/zzz-apcu.ini' + shouldExist: true + permissions: '-r--r--r--' + uid: 0 + gid: 0 + + - name: 'opcache config exists' + path: '/usr/local/etc/php/conf.d/zzz-opcache.ini' + shouldExist: true + permissions: '-r--r--r--' + uid: 0 + gid: 0 + + - name: 'php-fpm tuning config exists' + path: '/usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf' + shouldExist: true + permissions: '-r--r--r--' + uid: 0 + gid: 0 + + - name: 'php hardening config exists' + path: '/usr/local/etc/php/conf.d/zzz-php-hardening.ini' + shouldExist: true + permissions: '-r--r--r--' + uid: 0 + gid: 0 + + - name: 'nginx.conf exists' + path: '/etc/nginx/nginx.conf' + shouldExist: true + permissions: '-r--r--r--' + uid: 0 + gid: 0 + + - name: 'nginx mime.types exists' + path: '/etc/nginx/mime.types' + shouldExist: true + permissions: '-r--r--r--' + uid: 0 + gid: 0 + + - name: 'supervisord.conf exists' + path: '/etc/supervisor/supervisord.conf' + shouldExist: true + permissions: '-r--r--r--' + uid: 0 + gid: 0 + + - name: 'supervisor app.conf exists' + path: '/etc/supervisor/conf.d/app.conf' + shouldExist: true + permissions: '-r--r--r--' + uid: 0 + gid: 0 + + - name: 'GeoIP.dat exists' + path: '/usr/share/GeoIP/GeoIP.dat' + shouldExist: true + permissions: '-rw-r--r--' + + - name: 'GeoIPv6.dat exists' + path: '/usr/share/GeoIP/GeoIPv6.dat' + shouldExist: true + permissions: '-rw-r--r--' + +commandTests: + - name: 'apcu config checksum' + command: 'sha256sum' + args: ['/usr/local/etc/php/conf.d/zzz-apcu.ini'] + expectedOutput: + - 'db8d511610fd562151560c67707d4712900164b371687e4cb75f15f6fd62a9d6' + + - name: 'opcache config checksum' + command: 'sha256sum' + args: ['/usr/local/etc/php/conf.d/zzz-opcache.ini'] + expectedOutput: + - 'f37b923b4f54a8062782cef3cd260ea5cdac5b9f5cfa2a17915168dd17e7a433' + + - name: 'php-fpm tuning config checksum' + command: 'sha256sum' + args: ['/usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf'] + expectedOutput: + - '0d66730a9658f8c8553e73878b214a5c96084248a406660f593299f8dc8940ab' + + - name: 'php hardening config checksum' + command: 'sha256sum' + args: ['/usr/local/etc/php/conf.d/zzz-php-hardening.ini'] + expectedOutput: + - '489ba97dca079d84e7dc21afb68b0acf7954da8ad150279be70053dce7243f83' + + - name: 'nginx.conf checksum' + command: 'sha256sum' + args: ['/etc/nginx/nginx.conf'] + expectedOutput: + - '5781e761d4fff195797e1461fb85b3e5381fb6f0eef5e6e7463ec9f3b96f399b' + + - name: 'nginx mime.types checksum' + command: 'sha256sum' + args: ['/etc/nginx/mime.types'] + expectedOutput: + - 'ac27e1f587ecebc46ded3265479efdc6cb2f711c22e8221dadb00b7b4db55369' + + - name: 'supervisord.conf checksum' + command: 'sha256sum' + args: ['/etc/supervisor/supervisord.conf'] + expectedOutput: + - '7c1b6af616372d69f9beb279834b4b9bab0deb31ed454a21193b563817bf9304' + + - name: 'supervisor app.conf checksum' + command: 'sha256sum' + args: ['/etc/supervisor/conf.d/app.conf'] + expectedOutput: + - 'ffaca82839725c81b62f59a5da6fc941f2643eee5e649654725e01c80b28b1b4' + + - name: 'default user uid is nobody' + command: 'id' + args: ['-u'] + exitCode: 0 + expectedOutput: ['65534'] + + - name: 'default user gid is nogroup' + command: 'id' + args: ['-g'] + exitCode: 0 + expectedOutput: ['65534'] + + - name: 'php-fpm config test' + command: '/usr/local/sbin/php-fpm' + args: ['-t'] + exitCode: 0 + + - name: 'nginx config test' + command: '/usr/sbin/nginx' + args: ['-t'] + exitCode: 0 + expectedError: + - 'nginx: the configuration file /etc/nginx/nginx.conf syntax is ok' + - 'nginx: configuration file /etc/nginx/nginx.conf test is successful' + + - name: 'amqp extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i amqp'] + exitCode: 0 + expectedOutput: ['amqp'] + + - name: 'apcu extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i apcu'] + exitCode: 0 + expectedOutput: ['apcu'] + + - name: 'bcmath extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i bcmath'] + exitCode: 0 + expectedOutput: ['bcmath'] + + - name: 'bz2 extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i bz2'] + exitCode: 0 + expectedOutput: ['bz2'] + + - name: 'exif extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i exif'] + exitCode: 0 + expectedOutput: ['exif'] + + - name: 'gd extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i gd'] + exitCode: 0 + expectedOutput: ['gd'] + + - name: 'iconv extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i iconv'] + exitCode: 0 + expectedOutput: ['iconv'] + + - name: 'igbinary extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i igbinary'] + exitCode: 0 + expectedOutput: ['igbinary'] + + - name: 'imap extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i imap'] + exitCode: 0 + expectedOutput: ['imap'] + + - name: 'imagick extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i imagick'] + exitCode: 0 + expectedOutput: ['imagick'] + + - name: 'intl extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i intl'] + exitCode: 0 + expectedOutput: ['intl'] + + - name: 'lz4 extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i lz4'] + exitCode: 0 + expectedOutput: ['lz4'] + + - name: 'mailparse extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i mailparse'] + exitCode: 0 + expectedOutput: ['mailparse'] + + - name: 'mbstring extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i mbstring'] + exitCode: 0 + expectedOutput: ['mbstring'] + + - name: 'memcached extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i memcached'] + exitCode: 0 + expectedOutput: ['memcached'] + + - name: 'msgpack extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i msgpack'] + exitCode: 0 + expectedOutput: ['msgpack'] + + - name: 'pcntl extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i pcntl'] + exitCode: 0 + expectedOutput: ['pcntl'] + + - name: 'pdo_mysql extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i pdo_mysql'] + exitCode: 0 + expectedOutput: ['pdo_mysql'] + + - name: 'pdo_pgsql extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i pdo_pgsql'] + exitCode: 0 + expectedOutput: ['pdo_pgsql'] + + - name: 'pgsql extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i pgsql'] + exitCode: 0 + expectedOutput: ['pgsql'] + + - name: 'posix extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i posix'] + exitCode: 0 + expectedOutput: ['posix'] + + - name: 'redis extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i redis'] + exitCode: 0 + expectedOutput: ['redis'] + + - name: 'soap extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i soap'] + exitCode: 0 + expectedOutput: ['soap'] + + - name: 'sockets extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i sockets'] + exitCode: 0 + expectedOutput: ['sockets'] + + - name: 'sodium extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i sodium'] + exitCode: 0 + expectedOutput: ['sodium'] + + - name: 'tidy extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i tidy'] + exitCode: 0 + expectedOutput: ['tidy'] + + - name: 'xmlreader extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i xmlreader'] + exitCode: 0 + expectedOutput: ['xmlreader'] + + - name: 'zip extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i zip'] + exitCode: 0 + expectedOutput: ['zip'] + + - name: 'zstd extension is installed' + command: 'sh' + args: ['-c', 'php -m | grep -i zstd'] + exitCode: 0 + expectedOutput: ['zstd'] diff --git a/tests/php-lol.yaml b/tests/php-lol.yaml index 5ea63196..ebc07774 100644 --- a/tests/php-lol.yaml +++ b/tests/php-lol.yaml @@ -112,7 +112,7 @@ commandTests: command: 'sha256sum' args: ['/usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf'] expectedOutput: - - '0d66730a9658f8c8553e73878b214a5c96084248a406660f593299f8dc8940ab' + - 'e3772ca736903a1a4c27a715adae6c2ef35059119b527cefb30bac50af94ffef' - name: 'php hardening config checksum' command: 'sha256sum' @@ -124,7 +124,7 @@ commandTests: command: 'sha256sum' args: ['/etc/nginx/nginx.conf'] expectedOutput: - - '643f26a37d80bd94b983ab46f80b14b78ede41e3bee12be79a7b4ebebd43e426' + - '0c21ca2a7522fee98b6d5a0f28e0f6b1840d3df4d23b0b182b5c45c9d8b5ff8f' - name: 'nginx mime.types checksum' command: 'sha256sum' @@ -136,25 +136,13 @@ commandTests: command: 'sha256sum' args: ['/etc/supervisor/supervisord.conf'] expectedOutput: - - '7c1b6af616372d69f9beb279834b4b9bab0deb31ed454a21193b563817bf9304' + - 'cbf3f7370b1fd9f24360c20cc9e909f3298635d456fa76d97f531af0136a390c' - name: 'supervisor app.conf checksum' command: 'sha256sum' args: ['/etc/supervisor/conf.d/app.conf'] expectedOutput: - - 'ffaca82839725c81b62f59a5da6fc941f2643eee5e649654725e01c80b28b1b4' - - - name: 'default user uid is nobody' - command: 'id' - args: ['-u'] - exitCode: 0 - expectedOutput: ['65534'] - - - name: 'default user gid is nogroup' - command: 'id' - args: ['-g'] - exitCode: 0 - expectedOutput: ['65534'] + - 'bbdd21d87a9b30770de6b434673caf6594eb67bc4ff5c124f8c0ccb453c62d6b' - name: 'php-fpm config test' command: '/usr/local/sbin/php-fpm' From 2d90723396575e05a77ffd7e0f514243a75d9eb5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:10:05 +0000 Subject: [PATCH 5/8] fix(php-lol): harden rootless variant coverage Co-authored-by: bdossantos <245284+bdossantos@users.noreply.github.com> --- .github/actions/docker/action.yml | 2 +- .../php-lol/zzz-php-fpm-tuning.rootless.conf | 3 --- tests/php-lol-rootless.yaml | 20 ++++++++++++++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/actions/docker/action.yml b/.github/actions/docker/action.yml index 27ef69b7..b672061e 100644 --- a/.github/actions/docker/action.yml +++ b/.github/actions/docker/action.yml @@ -36,7 +36,7 @@ runs: tags=bdossantos/${image_name}:latest,bdossantos/${image_name}:${version},bdossantos/${image_name}:${version}-${vcs_ref},bdossantos/${image_name}:${version%.*} if [[ -f "$(dirname ${{ inputs.dockerfile }})/.rootless" ]]; then rootless=true - rootless_tags=bdossantos/${image_name}:${version}-rootless,bdossantos/${image_name}:${version%.*}-rootless + rootless_tags=bdossantos/${image_name}:${version}-rootless,bdossantos/${image_name}:${version}-${vcs_ref}-rootless,bdossantos/${image_name}:${version%.*}-rootless fi cache_image=bdossantos/${image_name}:buildcache echo "build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT diff --git a/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf b/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf index a926111c..44ac9b8c 100644 --- a/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf +++ b/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf @@ -15,8 +15,5 @@ ping.response = pong pm = static pm.max_children = 64 pm.max_requests = 1024 -pm.max_spare_servers = 64 -pm.process_idle_timeout = 10s -pm.start_servers = 16 pm.status_path = /php-fpm-status rlimit_files = 65535 diff --git a/tests/php-lol-rootless.yaml b/tests/php-lol-rootless.yaml index 5ce4e322..ee9be6a7 100644 --- a/tests/php-lol-rootless.yaml +++ b/tests/php-lol-rootless.yaml @@ -112,7 +112,7 @@ commandTests: command: 'sha256sum' args: ['/usr/local/etc/php-fpm.d/zzz-php-fpm-tuning.conf'] expectedOutput: - - '0d66730a9658f8c8553e73878b214a5c96084248a406660f593299f8dc8940ab' + - '3832a8a0902e318692ddee03be0a1d85d0ec8247388dac04863eff46313fe867' - name: 'php hardening config checksum' command: 'sha256sum' @@ -156,6 +156,24 @@ commandTests: exitCode: 0 expectedOutput: ['65534'] + - name: 'rootless supervisord can start services' + command: 'sh' + args: + - '-ceu' + - | + /usr/bin/supervisord -c /etc/supervisor/supervisord.conf & + pid=$! + trap 'kill "$pid"' EXIT + for _ in 1 2 3 4 5; do + if /usr/bin/supervisorctl status >/tmp/supervisor-status; then + break + fi + sleep 1 + done + grep -E '^php-fpm\\s+RUNNING' /tmp/supervisor-status + grep -E '^nginx\\s+RUNNING' /tmp/supervisor-status + exitCode: 0 + - name: 'php-fpm config test' command: '/usr/local/sbin/php-fpm' args: ['-t'] From 91c95028ab60b7ea7da8098bd25d714ab90baf65 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:10:46 +0000 Subject: [PATCH 6/8] test(php-lol): keep rootless checks read-only safe Co-authored-by: bdossantos <245284+bdossantos@users.noreply.github.com> --- tests/php-lol-rootless.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/php-lol-rootless.yaml b/tests/php-lol-rootless.yaml index ee9be6a7..aff52e30 100644 --- a/tests/php-lol-rootless.yaml +++ b/tests/php-lol-rootless.yaml @@ -165,13 +165,13 @@ commandTests: pid=$! trap 'kill "$pid"' EXIT for _ in 1 2 3 4 5; do - if /usr/bin/supervisorctl status >/tmp/supervisor-status; then + if /usr/bin/supervisorctl status >/dev/shm/supervisor-status; then break fi sleep 1 done - grep -E '^php-fpm\\s+RUNNING' /tmp/supervisor-status - grep -E '^nginx\\s+RUNNING' /tmp/supervisor-status + grep -E '^php-fpm\\s+RUNNING' /dev/shm/supervisor-status + grep -E '^nginx\\s+RUNNING' /dev/shm/supervisor-status exitCode: 0 - name: 'php-fpm config test' From 905a8e50974df30cb111d1c19b2285a4c22c07e7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:11:39 +0000 Subject: [PATCH 7/8] fix(ci): validate rootless php-lol startup Co-authored-by: bdossantos <245284+bdossantos@users.noreply.github.com> --- .github/actions/docker/action.yml | 2 +- Makefile | 18 ++++++++++++++++++ tests/php-lol-rootless.yaml | 4 ++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/actions/docker/action.yml b/.github/actions/docker/action.yml index b672061e..a1d8745e 100644 --- a/.github/actions/docker/action.yml +++ b/.github/actions/docker/action.yml @@ -36,7 +36,7 @@ runs: tags=bdossantos/${image_name}:latest,bdossantos/${image_name}:${version},bdossantos/${image_name}:${version}-${vcs_ref},bdossantos/${image_name}:${version%.*} if [[ -f "$(dirname ${{ inputs.dockerfile }})/.rootless" ]]; then rootless=true - rootless_tags=bdossantos/${image_name}:${version}-rootless,bdossantos/${image_name}:${version}-${vcs_ref}-rootless,bdossantos/${image_name}:${version%.*}-rootless + rootless_tags=bdossantos/${image_name}:latest-rootless,bdossantos/${image_name}:${version}-rootless,bdossantos/${image_name}:${version}-${vcs_ref}-rootless,bdossantos/${image_name}:${version%.*}-rootless fi cache_image=bdossantos/${image_name}:buildcache echo "build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT diff --git a/Makefile b/Makefile index 03b6ce93..3bfcb7e1 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,24 @@ container-structure-test: ## Run container-structure-test @$(CWD)/bin/container-structure-test test --image bdossantos/php-lol83-rootless --config tests/php-lol-rootless.yaml @$(CWD)/bin/container-structure-test test --image bdossantos/php-lol84-rootless --config tests/php-lol-rootless.yaml @$(CWD)/bin/container-structure-test test --image bdossantos/php-lol85-rootless --config tests/php-lol-rootless.yaml + @for image in bdossantos/php-lol83-rootless bdossantos/php-lol84-rootless bdossantos/php-lol85-rootless; do \ + docker run --rm --read-only --tmpfs /dev/shm --entrypoint sh $$image -ceu '\ + /usr/bin/supervisord -c /etc/supervisor/supervisord.conf & \ + pid=$$!; \ + trap "kill $$pid" EXIT; \ + rm -f /dev/shm/supervisor-status; \ + started=; \ + for _ in 1 2 3 4 5; do \ + if /usr/bin/supervisorctl status >/dev/shm/supervisor-status; then \ + started=1; \ + break; \ + fi; \ + sleep 1; \ + done; \ + test -n "$$started"; \ + grep -E "^php-fpm\\s+RUNNING" /dev/shm/supervisor-status; \ + grep -E "^nginx\\s+RUNNING" /dev/shm/supervisor-status'; \ + done @$(CWD)/bin/container-structure-test test --image bdossantos/pint --config tests/pint.yaml @$(CWD)/bin/container-structure-test test --image bdossantos/python-github-backup --config tests/python-github-backup.yaml @$(CWD)/bin/container-structure-test test --image bdossantos/radicale --config tests/radicale.yaml diff --git a/tests/php-lol-rootless.yaml b/tests/php-lol-rootless.yaml index aff52e30..2644844b 100644 --- a/tests/php-lol-rootless.yaml +++ b/tests/php-lol-rootless.yaml @@ -164,12 +164,16 @@ commandTests: /usr/bin/supervisord -c /etc/supervisor/supervisord.conf & pid=$! trap 'kill "$pid"' EXIT + rm -f /dev/shm/supervisor-status + started= for _ in 1 2 3 4 5; do if /usr/bin/supervisorctl status >/dev/shm/supervisor-status; then + started=1 break fi sleep 1 done + test -n "$started" grep -E '^php-fpm\\s+RUNNING' /dev/shm/supervisor-status grep -E '^nginx\\s+RUNNING' /dev/shm/supervisor-status exitCode: 0 From 992a7c83e1d66d9354e8402c14a972f4d326847e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:12:11 +0000 Subject: [PATCH 8/8] Changes before error encountered Agent-Logs-Url: https://github.com/bdossantos/dockerfiles/sessions/10b97bbf-9e58-40c0-a2ac-cfc3c4b8f3c4 Co-authored-by: bdossantos <245284+bdossantos@users.noreply.github.com> --- dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf b/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf index 44ac9b8c..f051ccec 100644 --- a/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf +++ b/dockerfiles/php-lol/zzz-php-fpm-tuning.rootless.conf @@ -9,6 +9,7 @@ group = nogroup access.log = /dev/null catch_workers_output = yes clear_env = no +listen = 127.0.0.1:9000 listen.backlog = 65535 ping.path = /php-fpm-ping ping.response = pong