-
Notifications
You must be signed in to change notification settings - Fork 13
Add GitHub workflows for building Alpine PHP #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
96a74e7
cc5a3ae
69fc6fc
0424222
cf3404a
8bfac77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| # syntax=docker/dockerfile:1.7 | ||
| # Alpine test image with PHP built from source in NTS mode | ||
| # Used for testing the extension on musl-based systems | ||
|
|
||
| ARG PHP_VERSION=8.3 | ||
| ARG PHP_SRC_REF=PHP-${PHP_VERSION} | ||
|
|
||
| FROM alpine:3.21 AS base | ||
| SHELL ["/bin/ash", "-eo", "pipefail", "-c"] | ||
|
|
||
| ENV TZ=Etc/UTC \ | ||
| LC_ALL=C.UTF-8 \ | ||
| LANG=C.UTF-8 \ | ||
| PHP_VERSION=${PHP_VERSION} | ||
|
|
||
| RUN apk add --no-cache \ | ||
| bash curl git wget make gcc g++ autoconf bison re2c pkgconf \ | ||
| libxml2-dev sqlite-dev curl-dev openssl-dev \ | ||
| libzip-dev oniguruma-dev libjpeg-turbo-dev libpng-dev libwebp-dev \ | ||
| icu-dev readline-dev libxslt-dev mariadb-connector-c-dev \ | ||
| linux-headers xz tar ca-certificates \ | ||
| nginx mariadb mariadb-client \ | ||
| python3 py3-pip py3-flask py3-requests py3-psutil \ | ||
| procps | ||
|
|
||
| FROM base AS php-build | ||
| ARG PHP_SRC_REF | ||
| WORKDIR /usr/src | ||
| RUN git clone --depth 1 --branch "${PHP_SRC_REF}" https://github.com/php/php-src.git | ||
| WORKDIR /usr/src/php-src | ||
|
|
||
| RUN sed -i 's/\[\([0-9]\+\.[0-9]\+\.[0-9]\+\)-dev\]/[\1]/' configure.ac | ||
| RUN ./buildconf --force | ||
|
|
||
| RUN mkdir -p /usr/local/etc/php/conf.d | ||
|
|
||
| RUN ./configure \ | ||
| --prefix=/usr/local \ | ||
| --with-config-file-path=/usr/local/lib \ | ||
| --with-config-file-scan-dir=/usr/local/etc/php/conf.d \ | ||
| --enable-fpm \ | ||
| --enable-mbstring \ | ||
| --enable-pcntl \ | ||
| --enable-cgi \ | ||
| --with-extra-version="" \ | ||
| --with-curl \ | ||
| --with-mysqli \ | ||
| --with-openssl \ | ||
| --with-zlib \ | ||
| --with-zip \ | ||
| --disable-zts \ | ||
| && make -j"$(nproc)" \ | ||
| && make install \ | ||
| && strip /usr/local/bin/php /usr/local/sbin/php-fpm || true | ||
|
|
||
| FROM base AS final | ||
| COPY --from=php-build /usr/local /usr/local | ||
|
|
||
| RUN EXTENSION_DIR=$(php -i | grep "^extension_dir" | awk '{print $3}') && \ | ||
| if [ -z "$EXTENSION_DIR" ]; then \ | ||
| echo "Error: Could not determine extension_dir"; \ | ||
| exit 1; \ | ||
| fi && \ | ||
| mkdir -p "$EXTENSION_DIR" | ||
|
|
||
| RUN php -v | grep -v "ZTS" >/dev/null || (echo "ERROR: ZTS is enabled but should be NTS!" && exit 1) && \ | ||
| php -m | grep -E 'curl|mysqli' >/dev/null | ||
|
|
||
| ENV PATH="/usr/local/bin:${PATH}" | ||
|
|
||
| RUN ln -sf /usr/local/bin/php /usr/bin/php && \ | ||
| ln -sf /usr/local/sbin/php-fpm /usr/sbin/php-fpm || true && \ | ||
| ln -sf /usr/local/bin/php-cgi /usr/bin/php-cgi | ||
|
|
||
| # Create /etc/httpd so the test harness uses the CentOS-style php-fpm config path | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The RUN starting at line 75 chains many filesystem modifications, config writes, php-fpm tests, and symlink commands with &&/||. Split into smaller RUN steps to improve readability and isolate failures. Details✨ AI Reasoning 🔧 How do I fix it? Reply |
||
| RUN mkdir -p /etc/httpd && \ | ||
| mkdir -p /etc/php-fpm.d && \ | ||
| mkdir -p /run/php-fpm && \ | ||
| mkdir -p /var/run && \ | ||
| mkdir -p /var/log/php-fpm && \ | ||
| mkdir -p /usr/local/etc/php-fpm.d && \ | ||
| mkdir -p /usr/local/etc/php/conf.d && \ | ||
| ln -sf /usr/local/etc/php/conf.d /etc/php.d || true && \ | ||
| echo "[global]" > /usr/local/etc/php-fpm.conf && \ | ||
| echo "pid = /run/php-fpm/php-fpm.pid" >> /usr/local/etc/php-fpm.conf && \ | ||
| echo "error_log = /var/log/php-fpm/error.log" >> /usr/local/etc/php-fpm.conf && \ | ||
| echo "daemonize = yes" >> /usr/local/etc/php-fpm.conf && \ | ||
| echo "include=/usr/local/etc/php-fpm.d/*.conf" >> /usr/local/etc/php-fpm.conf && \ | ||
| echo "include=/etc/php-fpm.d/*.conf" >> /usr/local/etc/php-fpm.conf && \ | ||
| echo "[www]" > /usr/local/etc/php-fpm.d/www.conf && \ | ||
| echo "user = root" >> /usr/local/etc/php-fpm.d/www.conf && \ | ||
| echo "group = root" >> /usr/local/etc/php-fpm.d/www.conf && \ | ||
| echo "listen = 127.0.0.1:9000" >> /usr/local/etc/php-fpm.d/www.conf && \ | ||
| echo "listen.owner = root" >> /usr/local/etc/php-fpm.d/www.conf && \ | ||
| echo "listen.group = root" >> /usr/local/etc/php-fpm.d/www.conf && \ | ||
| echo "pm = dynamic" >> /usr/local/etc/php-fpm.d/www.conf && \ | ||
| echo "pm.max_children = 5" >> /usr/local/etc/php-fpm.d/www.conf && \ | ||
| echo "pm.start_servers = 2" >> /usr/local/etc/php-fpm.d/www.conf && \ | ||
| echo "pm.min_spare_servers = 1" >> /usr/local/etc/php-fpm.d/www.conf && \ | ||
| echo "pm.max_spare_servers = 3" >> /usr/local/etc/php-fpm.d/www.conf && \ | ||
| php-fpm -t -y /usr/local/etc/php-fpm.conf 2>&1 | grep -v "Nothing matches the include pattern" || true && \ | ||
| php-fpm -t -y /usr/local/etc/php-fpm.conf >/dev/null 2>&1 || \ | ||
| (echo "PHP-FPM config test failed" && exit 1) && \ | ||
| ln -sf /usr/local/etc/php-fpm.conf /etc/php-fpm.conf | ||
|
|
||
| # Configure nginx to include /etc/nginx/conf.d/ (expected by test harness) | ||
| RUN mkdir -p /etc/nginx/conf.d && \ | ||
| awk '/include.*http\.d/{print; print " include /etc/nginx/conf.d/*.conf;"; next}1' \ | ||
| /etc/nginx/nginx.conf > /tmp/nginx.conf && \ | ||
| mv /tmp/nginx.conf /etc/nginx/nginx.conf | ||
|
|
||
| # MySQL socket path for mysqli | ||
| RUN echo "mysqli.default_socket = /var/lib/mysql/mysql.sock" > /usr/local/etc/php/conf.d/mysql-socket.ini | ||
|
|
||
| # MariaDB helper script | ||
| RUN mkdir -p /usr/local/bin /var/lib/mysql /run/mysqld && \ | ||
| printf '%s\n' \ | ||
| '#!/bin/sh' \ | ||
| 'set -e' \ | ||
| 'mkdir -p /var/lib/mysql /run/mysqld' \ | ||
| 'chown -R mysql:mysql /var/lib/mysql /run/mysqld' \ | ||
| 'if [ ! -d /var/lib/mysql/mysql ]; then' \ | ||
| ' mysql_install_db --user=mysql --datadir=/var/lib/mysql' \ | ||
| 'fi' \ | ||
| 'mysqld --user=mysql --datadir=/var/lib/mysql --socket=/var/lib/mysql/mysql.sock &' \ | ||
| 'pid=$!' \ | ||
| 'for i in $(seq 1 30); do mysqladmin --socket=/var/lib/mysql/mysql.sock ping --silent 2>/dev/null && break; sleep 1; done' \ | ||
| 'mysql --socket=/var/lib/mysql/mysql.sock -u root -e "CREATE DATABASE IF NOT EXISTS db;" || true' \ | ||
| 'mysql --socket=/var/lib/mysql/mysql.sock -u root -e "ALTER USER '"'"'root'"'"'@'"'"'localhost'"'"' IDENTIFIED BY '"'"'pwd'"'"'; FLUSH PRIVILEGES;" || true' \ | ||
| 'wait $pid' \ | ||
| > /usr/local/bin/start-mariadb && \ | ||
| chmod +x /usr/local/bin/start-mariadb | ||
|
|
||
| WORKDIR /work | ||
| CMD ["bash"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| # syntax=docker/dockerfile:1.7 | ||
| # Alpine image with PHP built from source in NTS mode | ||
| # Used for building the PHP extension on musl-based systems | ||
|
|
||
| ARG PHP_VERSION=8.3 | ||
| ARG PHP_SRC_REF=PHP-${PHP_VERSION} | ||
|
|
||
| FROM alpine:3.21 AS base | ||
| SHELL ["/bin/ash", "-eo", "pipefail", "-c"] | ||
|
|
||
| ENV TZ=Etc/UTC \ | ||
| LC_ALL=C.UTF-8 \ | ||
| LANG=C.UTF-8 | ||
|
|
||
| RUN apk add --no-cache \ | ||
| bash curl git wget make gcc g++ autoconf bison re2c pkgconf \ | ||
| libxml2-dev sqlite-dev curl-dev openssl-dev \ | ||
| libzip-dev oniguruma-dev libjpeg-turbo-dev libpng-dev libwebp-dev \ | ||
| icu-dev readline-dev libxslt-dev mariadb-connector-c-dev \ | ||
| linux-headers xz tar ca-certificates | ||
|
|
||
| FROM base AS php-src | ||
| ARG PHP_SRC_REF | ||
| WORKDIR /usr/src | ||
| RUN git clone --depth 1 --branch "${PHP_SRC_REF}" https://github.com/php/php-src.git | ||
| WORKDIR /usr/src/php-src | ||
| RUN ./buildconf --force | ||
|
|
||
| FROM php-src AS php-build | ||
| RUN ./configure \ | ||
| --prefix=/usr/local \ | ||
| --with-config-file-path=/usr/local/lib \ | ||
| --with-config-file-scan-dir=/usr/local/etc/php/conf.d \ | ||
| --enable-mbstring \ | ||
| --enable-pcntl \ | ||
| --enable-intl \ | ||
| --with-curl \ | ||
| --with-mysqli \ | ||
| --with-openssl \ | ||
| --with-zlib \ | ||
| --with-zip \ | ||
| && make -j"$(nproc)" \ | ||
| && make install \ | ||
| && strip /usr/local/bin/php || true | ||
|
|
||
| FROM base AS dev | ||
| COPY --from=php-build /usr/local /usr/local | ||
| RUN php -v && php -m | grep -E 'curl|mysqli' >/dev/null | ||
| ENV PATH="/usr/local/bin:${PATH}" | ||
|
|
||
| RUN mkdir -p /usr/local/etc/php/conf.d | ||
| WORKDIR /work | ||
| CMD ["php", "-v"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # Alpine-based image for building Go shared libraries with custom Go fork | ||
| # that supports c-shared buildmode on musl-based systems. | ||
| FROM alpine:3.21 | ||
|
|
||
| ARG GO_RELEASE_TAG=devel-go1.27-tlsdesc.1 | ||
|
|
||
| RUN apk add --no-cache \ | ||
| bash curl git make gcc g++ musl-dev \ | ||
| protobuf protobuf-dev | ||
|
|
||
| RUN ARCH=$(uname -m) && \ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The RUN at line 11 combines architecture detection, conditional assignment, download, extraction and cleanup. Break into separate steps (detect/assign, download, extract, cleanup) for clarity and easier failure diagnosis. Details✨ AI Reasoning 🔧 How do I fix it? Reply |
||
| if [ "$ARCH" = "x86_64" ]; then GO_ARCH="amd64"; \ | ||
| elif [ "$ARCH" = "aarch64" ]; then GO_ARCH="arm64"; fi && \ | ||
| curl -fsSL -o /tmp/go.tar.gz \ | ||
| "https://github.com/AikidoSec/go/releases/download/${GO_RELEASE_TAG}/${GO_RELEASE_TAG}.linux-${GO_ARCH}.tar.gz" && \ | ||
| tar -C /usr/local -xzf /tmp/go.tar.gz && \ | ||
| rm /tmp/go.tar.gz | ||
|
|
||
| ENV PATH="/usr/local/go/bin:${PATH}" | ||
| ENV GOPATH="/go" | ||
| ENV GOBIN="/go/bin" | ||
| ENV PATH="${GOBIN}:${PATH}" | ||
|
|
||
| RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \ | ||
| go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest | ||
|
|
||
| WORKDIR /workspace | ||
|
|
||
| CMD ["/bin/bash"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| name: Build Alpine PHP test images (NTS) | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| paths: | ||
| - .github/workflows/Dockerfile.alpine-php-test-nts | ||
| - .github/workflows/build-alpine-php-test-images-nts.yml | ||
|
|
||
| env: | ||
| REGISTRY: ghcr.io | ||
| IMAGE_NAME: aikidosec/firewall-php-test-alpine-nts | ||
| VERSION: v1 | ||
|
|
||
| jobs: | ||
| build-amd64: | ||
| runs-on: ubuntu-24.04 | ||
| strategy: | ||
| matrix: | ||
| php_version: ['7.4','8.0','8.1','8.2','8.3','8.4','8.5'] | ||
| fail-fast: false | ||
| permissions: { contents: read, packages: write } | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: docker/setup-buildx-action@v3 | ||
| - uses: docker/login-action@v3 | ||
| with: | ||
| registry: ${{ env.REGISTRY }} | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Build & push (amd64) | ||
| uses: docker/build-push-action@v6 | ||
| with: | ||
| context: . | ||
| file: .github/workflows/Dockerfile.alpine-php-test-nts | ||
| platforms: linux/amd64 | ||
| push: true | ||
| build-args: | | ||
| PHP_VERSION=${{ matrix.php_version }} | ||
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ matrix.php_version }}-amd64-${{ env.VERSION }} | ||
|
|
||
| build-arm64: | ||
| runs-on: ubuntu-24.04-arm | ||
| strategy: | ||
| matrix: | ||
| php_version: ['7.4','8.0','8.1','8.2','8.3','8.4','8.5'] | ||
| fail-fast: false | ||
| permissions: { contents: read, packages: write } | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: docker/setup-buildx-action@v3 | ||
| - uses: docker/login-action@v3 | ||
| with: | ||
| registry: ${{ env.REGISTRY }} | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Build & push (arm64) | ||
| uses: docker/build-push-action@v6 | ||
| with: | ||
| context: . | ||
| file: .github/workflows/Dockerfile.alpine-php-test-nts | ||
| platforms: linux/arm64 | ||
| push: true | ||
| build-args: | | ||
| PHP_VERSION=${{ matrix.php_version }} | ||
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ matrix.php_version }}-arm64-${{ env.VERSION }} | ||
|
|
||
| publish-manifests: | ||
| runs-on: ubuntu-24.04 | ||
| needs: [build-amd64, build-arm64] | ||
| strategy: | ||
| matrix: | ||
| php_version: ['7.4','8.0','8.1','8.2','8.3','8.4','8.5'] | ||
| fail-fast: false | ||
| permissions: { contents: read, packages: write } | ||
| steps: | ||
| - uses: docker/setup-buildx-action@v3 | ||
| - uses: docker/login-action@v3 | ||
| with: | ||
| registry: ${{ env.REGISTRY }} | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Create multi-arch manifest | ||
| run: | | ||
| IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | ||
| V=${{ matrix.php_version }} | ||
| docker buildx imagetools create \ | ||
| --tag ${IMAGE}:${V}-${{ env.VERSION }} \ | ||
| ${IMAGE}:${V}-amd64-${{ env.VERSION }} \ | ||
| ${IMAGE}:${V}-arm64-${{ env.VERSION }} |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ZTS guard uses
php -v | grep -v "ZTS", which can still succeed when ZTS is enabled because otherphp -vlines don’t contain "ZTS", so the error branch may never run.Details
✨ AI Reasoning
1) The block is trying to fail the image build if PHP was compiled with ZTS.
2) It uses
php -v | grep -v "ZTS" >/dev/nullto decide success.3)
php -voutputs multiple lines; even if the version line contains "ZTS", other lines typically do not, sogrep -v "ZTS"still outputs something and exits 0.4) This means the code can silently pass the ZTS check when ZTS is enabled, contradicting the intended control-flow guard.
Reply
@AikidoSec feedback: [FEEDBACK]to get better review comments in the future.Reply
@AikidoSec ignore: [REASON]to ignore this issue.More info