diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 229ab42..6c8cdb1 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -1,12 +1,45 @@ -name: Publish Docker image +name: Build & Publish on: - push: - branches: ["master", "php*"] + workflow_call: + inputs: + version: + type: string + required: true + name: + type: string + required: true + template: + type: string + required: false + base: + type: string + required: true + xdebug_version: + type: string + required: true + redis_version: + type: string + required: true + imap_type: + type: string + required: true + imap_version: + type: string + required: true + php_errors_enabled: + type: boolean + required: true + variations: + type: string + required: true + push: + type: boolean + default: ${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} jobs: - push_to_registry: - name: Push Docker image to Docker Hub + build: + name: Build Docker image runs-on: ubuntu-latest permissions: @@ -17,6 +50,33 @@ jobs: - name: Check out the repo uses: actions/checkout@v4 + - name: install go-replace + env: + GOREPLACE_VERSION: 22.9.0 + run: | + wget -O /usr/local/bin/go-replace \ + https://github.com/webdevops/go-replace/releases/download/$GOREPLACE_VERSION/go-replace.linux.amd64 + chmod +x /usr/local/bin/go-replace + + - name: build Dockerfile + env: + DOCKER_BUILD_VERSION: ${{ inputs.version }} + DOCKER_BUILD_BASE: ${{ inputs.base }} + DOCKER_BUILD_XDEBUG_VERSION: ${{ inputs.xdebug_version }} + DOCKER_BUILD_REDIS_VERSION: ${{ inputs.redis_version }} + DOCKER_BUILD_IMAP_TYPE: ${{ inputs.imap_type }} + DOCKER_BUILD_IMAP_VERSION: ${{ inputs.imap_version }} + DOCKER_BUILD_PHP_ERRORS_ENABLED: ${{ inputs.php_errors_enabled && '1' || '0' }} + run: | + go-replace --mode=template ./${{ inputs.template }} -o ./Dockerfile + + - name: add Dockerfile to summary + run: | + echo '### Dockerfile generated for ${{ inputs.name }}' >> $GITHUB_STEP_SUMMARY + echo '```dockerfile' >> $GITHUB_STEP_SUMMARY + cat Dockerfile >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + - name: Log in to Docker Hub uses: docker/login-action@v3 with: @@ -28,22 +88,57 @@ jobs: uses: docker/metadata-action@v5 with: images: lojassimonetti/php-apache-oci8-composer + tags: | + type=raw,value=${{ inputs.name }},enable=true - - name: Should push? - id: shoudPush - run: | - if [[ ${{ github.event.ref }} = "refs/heads/master" ]]; then - echo "match=true" >> $GITHUB_OUTPUT - elif [[ ${{ github.event.ref }} =~ ^refs/heads/php[0-9]dot[0-9]$ ]]; then - echo "match=true" >> $GITHUB_OUTPUT - elif [[ ${{ github.event.ref }} =~ ^refs/heads/php[0-9]dot[0-9]-mongodb$ ]]; then - echo "match=true" >> $GITHUB_OUTPUT - fi + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: ${{ inputs.push }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + build_variations: + name: Build image variation + runs-on: ubuntu-latest + + needs: + - build + + strategy: + fail-fast: false + matrix: + variation: ${{ fromJson(inputs.variations) }} + + permissions: + packages: write + contents: read + + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: lojassimonetti/php-apache-oci8-composer + tags: | + type=raw,value=${{ inputs.name }}-${{ matrix.variation }},enable=true - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: . - push: ${{ steps.shoudPush.outputs.match == 'true' }} + build-args: IMAGE_BASE=lojassimonetti/php-apache-oci8-composer:${{ inputs.name }} + file: ./Dockerfile.${{ matrix.variation }} + push: ${{ inputs.push }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/setup-build.yaml b/.github/workflows/setup-build.yaml new file mode 100644 index 0000000..595b015 --- /dev/null +++ b/.github/workflows/setup-build.yaml @@ -0,0 +1,49 @@ +name: Publish Docker image + +on: + push: + +jobs: + setup: + name: Setup Matrix Build + runs-on: ubuntu-latest + + permissions: + packages: write + contents: read + + outputs: + versions: ${{ steps.read.outputs.versions }} + + steps: + - name: Check out the repo + uses: actions/checkout@v5 + + - name: read configs + id: read + run: | + echo "versions=$(cat config.json | jq . --compact-output)" >> "$GITHUB_OUTPUT" + + docker_build_push: + name: Build and Push + needs: + - setup + + strategy: + fail-fast: false + matrix: + config: ${{ fromJson(needs.setup.outputs.versions) }} + + uses: ./.github/workflows/docker-build.yaml + secrets: inherit + with: + name: ${{ matrix.config.name }} + base: ${{ matrix.config.base }} + template: ${{ matrix.config.template || 'Dockerfile.tmpl' }} + version: ${{ matrix.config.version }} + xdebug_version: ${{ matrix.config.xdebug_version }} + redis_version: ${{ matrix.config.redis_version }} + imap_version: ${{ matrix.config.imap_version }} + imap_type: ${{ matrix.config.imap_type }} + php_errors_enabled: ${{ matrix.config.php_errors_enabled }} + variations: ${{ toJson(matrix.config.variations) }} diff --git a/Dockerfile.grpc b/Dockerfile.grpc new file mode 100644 index 0000000..55003ba --- /dev/null +++ b/Dockerfile.grpc @@ -0,0 +1,10 @@ +ARG IMAGE_BASE +FROM ${IMAGE_BASE} + +USER root + +RUN echo "---> GRPC" && \ + pecl install grpc && \ + docker-php-ext-enable grpc + +USER www-data:www-data diff --git a/Dockerfile.mongodb b/Dockerfile.mongodb new file mode 100644 index 0000000..bff1a2e --- /dev/null +++ b/Dockerfile.mongodb @@ -0,0 +1,10 @@ +ARG IMAGE_BASE +FROM ${IMAGE_BASE} + +USER root + +RUN echo "---> Mongo DB" && \ + pecl install mongodb && \ + docker-php-ext-enable mongodb + +USER www-data:www-data diff --git a/Dockerfile.mongodb-1.21.0 b/Dockerfile.mongodb-1.21.0 new file mode 100644 index 0000000..d70b958 --- /dev/null +++ b/Dockerfile.mongodb-1.21.0 @@ -0,0 +1,10 @@ +ARG IMAGE_BASE +FROM ${IMAGE_BASE} + +USER root + +RUN echo "---> Mongo DB" && \ + pecl install mongodb-1.21.0 && \ + docker-php-ext-enable mongodb + +USER www-data:www-data diff --git a/Dockerfile.pgsql b/Dockerfile.pgsql new file mode 100644 index 0000000..c576bdf --- /dev/null +++ b/Dockerfile.pgsql @@ -0,0 +1,10 @@ +ARG IMAGE_BASE +FROM ${IMAGE_BASE} + +USER root + +RUN echo "---> PGSQL" && \ + apt-get update && apt-get install -y --no-install-recommends libpq-dev && \ + docker-php-ext-install pdo_pgsql + +USER www-data:www-data diff --git a/Dockerfile.swoole.tmpl b/Dockerfile.swoole.tmpl new file mode 100644 index 0000000..fc1cf79 --- /dev/null +++ b/Dockerfile.swoole.tmpl @@ -0,0 +1,118 @@ +{{ $version := float64 (env "DOCKER_BUILD_VERSION") -}} +FROM {{ env "DOCKER_BUILD_BASE" }} + +ENV \ + NR_ENABLED=false \ + NR_APP_NAME="" \ + NR_LICENSE_KEY="" \ + NR_VERSION="" \ + PHP_OPCACHE_ENABLED=false \ + SESSION_HANDLER=false \ + SESSION_HANDLER_NAME="" \ + SESSION_HANDLER_PATH="" \ + XDEBUG_AUTOSTART=false \ + XDEBUG_CONNECT_BACK=true \ + XDEBUG_ENABLED=false \ + XDEBUG_IDEKEY="docker" \ + XDEBUG_VERSION="{{ if not (eq (env "DOCKER_BUILD_XDEBUG_VERSION") "") -}} + -{{ env "DOCKER_BUILD_XDEBUG_VERSION" }} + {{- end }}" \ + REDIS_VERSION="{{ if not (eq (env "DOCKER_BUILD_REDIS_VERSION") "") -}} + -{{ env "DOCKER_BUILD_REDIS_VERSION" }} + {{- end }}" \ + IMAP_VERSION="{{ if not (eq (env "DOCKER_BUILD_IMAP_VERSION") "") -}} + -{{ env "DOCKER_BUILD_IMAP_VERSION" }} + {{- end }}" \ + XDEBUG_REMOTE_PORT=9000 \ + PHP_EXTENSION_WDDX=1 \ + PHP_OPENSSL=1 \ + CONTAINER_STARTED_LOCK=/var/lock/container.starting + +RUN apt-get update && apt-get install -y --no-install-recommends wget vim supervisor libfreetype6-dev libjpeg-dev libjpeg62-turbo-dev \ + libmcrypt-dev libpng-dev libssl-dev libaio1 git libcurl4-openssl-dev libxslt-dev \ + libldap2-dev libicu-dev libc-client-dev libkrb5-dev libsqlite3-dev libedit-dev \ + sudo zlib1g zlib1g-dev libzip4 libzip-dev zip unzip librabbitmq-dev{{ if gt $version 7.4 }} musl-dev{{end}} && \ + rm -rf /var/lib/apt/lists/* + +RUN docker-php-ext-configure gd --with-jpeg \ + && docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ \ +{{- if eq (env "DOCKER_BUILD_IMAP_TYPE") "php-ext" }} + && docker-php-ext-configure imap --with-kerberos --with-imap-ssl \ +{{- end }} + && docker-php-ext-install -j$(nproc) bcmath gd pdo_mysql calendar exif gettext shmop soap sockets intl pcntl xsl ldap ftp{{ if eq (env "DOCKER_BUILD_IMAP_TYPE") "php-ext" }} imap{{end}} +{{- if eq (env "DOCKER_BUILD_IMAP_TYPE") "pecl" }} + +RUN echo "---> Adding IMAP" && \ + pecl install imap${IMAP_VERSION} && \ + docker-php-ext-enable imap +{{ end }} + +RUN echo "---> Adding Redis" && \ + pecl install redis${REDIS_VERSION} && \ + docker-php-ext-enable redis + +RUN echo "---> Adding xDebug" && \ + pecl install "xdebug${XDEBUG_VERSION}" + +RUN echo "---> Adding Zip" && \ + pecl install zip && \ + docker-php-ext-enable zip + +RUN echo "---> Adding AMQp" && \ + apt-get update && apt-get install -y -f librabbitmq-dev libssh-dev \ + && docker-php-source extract \ + && mkdir /usr/src/php/ext/amqp \ + && curl -L https://github.com/php-amqp/php-amqp/archive/master.tar.gz | tar -xzC /usr/src/php/ext/amqp --strip-components=1 \ + && docker-php-ext-install amqp \ + && docker-php-ext-enable amqp + +RUN echo "---> Configure Opcache" && \ + docker-php-ext-install opcache && \ + echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini && \ + echo "opcache.enable_cli=0" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini + +RUN echo "---> Swoole" && \ + pecl install swoole -D 'enable-http2="yes"' && \ + docker-php-ext-enable swoole + +RUN echo "---> Adding Tini" && \ + wget -O /tini https://github.com/krallin/tini/releases/download/v0.18.0/tini-static && \ + chmod +x /tini + +RUN echo "---> Adding NewRelic" && \ + apt-get update && apt-get install -y -q --no-install-recommends --no-install-suggests gnupg2 \ + && echo 'deb http://apt.newrelic.com/debian/ newrelic non-free' | sudo tee /etc/apt/sources.list.d/newrelic.list \ + && wget -O- https://download.newrelic.com/548C16BF.gpg | sudo apt-key add - \ + && sudo apt-get update && apt-get install -y -q --no-install-recommends --no-install-suggests newrelic-php5 \ + && NR_INSTALL_USE_CP_NOT_LN=1 NR_INSTALL_SILENT=1 newrelic-install install \ + && chown www-data:www-data /usr/local/etc/php/conf.d/newrelic.ini && chmod a+rw /usr/local/etc/php/conf.d/newrelic.ini \ + && apt-get remove -y gnupg2 && rm -rf /var/lib/apt/lists/* \ + && echo "newrelic.distributed_tracing_enabled = false" | sudo tee -a /usr/local/etc/php/conf.d/newrelic.ini \ + && echo "newrelic.application_logging.enabled = false" | sudo tee -a /usr/local/etc/php/conf.d/newrelic.ini \ + && echo "newrelic.enabled = false" | sudo tee -a /usr/local/etc/php/conf.d/newrelic.ini + +RUN echo "---> Config sudoers" && \ + echo "www-data ALL = ( ALL ) NOPASSWD: ALL" >> /etc/sudoers + +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer +RUN echo "---> Fix permissions" \ + && mkdir /var/www/.composer && chown -R www-data:www-data /var/www/.composer + +COPY configs/logs.conf /etc/apache2/conf-enabled/logs.conf +{{- if eq (env "DOCKER_BUILD_PHP_ERRORS_ENABLED") "1" }} +COPY configs/php-errors.ini /usr/local/etc/php/conf.d/php-errors.ini +{{ end }} +COPY ./bin /usr/bin/ + +RUN chmod a+x \ + /usr/bin/swoole-run \ + /usr/bin/xdebug-set-mode \ + /usr/bin/post-startup-hook + +USER www-data + +WORKDIR "/var/www/html" + +EXPOSE 8080 9001 + +CMD ["/tini", "--", "/usr/bin/swoole-run"] diff --git a/Dockerfile b/Dockerfile.tmpl similarity index 76% rename from Dockerfile rename to Dockerfile.tmpl index 0a66e12..f1e79d2 100644 --- a/Dockerfile +++ b/Dockerfile.tmpl @@ -1,13 +1,15 @@ -# Container Base -FROM php:8.4-apache-bookworm +{{ $version := float64 (env "DOCKER_BUILD_VERSION") -}} +FROM {{ env "DOCKER_BUILD_BASE" }} ENV \ NR_ENABLED=false \ + NR_DISTRIBUTED_TRACING_ENABLED=false \ + NR_APPLICATION_LOGGING_ENABLED=false \ + NR_IGNORE_DEFAULT_EXCEPTION=false \ + NR_IGNORED_EXECEPTIONS="" \ NR_APP_NAME="" \ NR_LICENSE_KEY="" \ NR_VERSION="" \ - NR_IGNORE_DEFAULT_EXCEPTION=false \ - NR_IGNORED_EXECEPTIONS="" \ PHP_OPCACHE_ENABLED=false \ SESSION_HANDLER=false \ SESSION_HANDLER_NAME="" \ @@ -16,9 +18,15 @@ ENV \ XDEBUG_CONNECT_BACK=true \ XDEBUG_ENABLED=false \ XDEBUG_IDEKEY="docker" \ - XDEBUG_VERSION="-3.4.1" \ - REDIS_VERSION="-6.1.0" \ - IMAP_VERSION="" \ + XDEBUG_VERSION="{{ if not (eq (env "DOCKER_BUILD_XDEBUG_VERSION") "") -}} + -{{ env "DOCKER_BUILD_XDEBUG_VERSION" }} + {{- end }}" \ + REDIS_VERSION="{{ if not (eq (env "DOCKER_BUILD_REDIS_VERSION") "") -}} + -{{ env "DOCKER_BUILD_REDIS_VERSION" }} + {{- end }}" \ + IMAP_VERSION="{{ if not (eq (env "DOCKER_BUILD_IMAP_VERSION") "") -}} + -{{ env "DOCKER_BUILD_IMAP_VERSION" }} + {{- end }}" \ XDEBUG_REMOTE_PORT=9000 \ PHP_EXTENSION_WDDX=1 \ PHP_OPENSSL=1 \ @@ -27,18 +35,23 @@ ENV \ RUN apt-get update && apt-get install -y --no-install-recommends wget vim supervisor libfreetype6-dev libjpeg-dev libjpeg62-turbo-dev \ libmcrypt-dev libpng-dev libssl-dev libaio1 git libcurl4-openssl-dev libxslt-dev \ libldap2-dev libicu-dev libc-client-dev libkrb5-dev libsqlite3-dev libedit-dev \ - sudo zlib1g zlib1g-dev libzip4 libzip-dev zip unzip librabbitmq-dev musl-dev && \ + sudo zlib1g zlib1g-dev libzip4 libzip-dev zip unzip librabbitmq-dev{{ if gt $version 7.4 }} musl-dev{{end}} && \ rm -rf /var/lib/apt/lists/* RUN a2enmod rewrite unique_id headers RUN docker-php-ext-configure gd --with-jpeg \ && docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ \ - && docker-php-ext-install -j$(nproc) bcmath gd pdo_mysql calendar exif gettext shmop soap sockets intl pcntl xsl ldap ftp +{{- if eq (env "DOCKER_BUILD_IMAP_TYPE") "php-ext" }} + && docker-php-ext-configure imap --with-kerberos --with-imap-ssl \ +{{- end }} + && docker-php-ext-install -j$(nproc) bcmath gd pdo_mysql calendar exif gettext shmop soap sockets intl pcntl xsl ldap ftp{{ if eq (env "DOCKER_BUILD_IMAP_TYPE") "php-ext" }} imap{{end}} +{{- if eq (env "DOCKER_BUILD_IMAP_TYPE") "pecl" }} RUN echo "---> Adding IMAP" && \ pecl install imap${IMAP_VERSION} && \ docker-php-ext-enable imap +{{ end }} RUN echo "---> Adding Redis" && \ pecl install redis${REDIS_VERSION} && \ @@ -52,12 +65,8 @@ RUN echo "---> Adding Zip" && \ docker-php-ext-enable zip RUN echo "---> Adding AMQp" && \ - apt-get update && apt-get install -y -f librabbitmq-dev libssh-dev \ - && docker-php-source extract \ - && mkdir /usr/src/php/ext/amqp \ - && curl -L https://github.com/php-amqp/php-amqp/archive/master.tar.gz | tar -xzC /usr/src/php/ext/amqp --strip-components=1 \ - && docker-php-ext-install amqp \ - && docker-php-ext-enable amqp + pecl install amqp && \ + docker-php-ext-enable amqp RUN echo "---> Configure Opcache" && \ docker-php-ext-install opcache && \ @@ -76,7 +85,7 @@ RUN echo "---> Adding NewRelic" && \ && NR_INSTALL_USE_CP_NOT_LN=1 NR_INSTALL_SILENT=1 newrelic-install install \ && cp /usr/lib/newrelic-php5/scripts/newrelic.ini.template /usr/local/etc/php/conf.d/newrelic.ini \ && chown www-data:www-data /usr/local/etc/php/conf.d/newrelic.ini && chmod a+rw /usr/local/etc/php/conf.d/newrelic.ini \ - && apt-get remove -y gnupg2 && rm -rf /var/lib/apt/lists/* #\ + && apt-get remove -y gnupg2 && rm -rf /var/lib/apt/lists/* \ && echo "newrelic.distributed_tracing_enabled = false" | sudo tee -a /usr/local/etc/php/conf.d/newrelic.ini \ && echo "newrelic.application_logging.enabled = false" | sudo tee -a /usr/local/etc/php/conf.d/newrelic.ini \ && echo "newrelic.enabled = false" | sudo tee -a /usr/local/etc/php/conf.d/newrelic.ini @@ -85,6 +94,7 @@ RUN echo "---> Config sudoers" && \ echo "www-data ALL = ( ALL ) NOPASSWD: ALL" >> /etc/sudoers COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + RUN echo "---> Fix permissions" \ && chown -R www-data:www-data /var/log/apache2 \ && mkdir /var/www/.composer && chown -R www-data:www-data /var/www/.composer @@ -92,7 +102,9 @@ RUN echo "---> Fix permissions" \ COPY configs/ports.conf /etc/apache2/ports.conf COPY configs/headers.conf /etc/apache2/conf-enabled/headers.conf COPY configs/logs.conf /etc/apache2/conf-enabled/logs.conf +{{- if eq (env "DOCKER_BUILD_PHP_ERRORS_ENABLED") "1" }} COPY configs/php-errors.ini /usr/local/etc/php/conf.d/php-errors.ini +{{ end }} COPY apache-run.sh /usr/bin/apache-run COPY ./bin /usr/bin/ diff --git a/Makefile b/Makefile index bb27d58..99f2740 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,37 @@ all: build IMAGE=lojassimonetti/php-apache-oci8-composer -tag=$(shell git branch | grep \* | cut -d ' ' -f2) -TAG=$(shell [[ "$(tag)" == "master" ]] && echo "latest" || echo $(tag)) +FILE=Dockerfile + +list-names: + @cat config.json|jq '.[]|.name' --raw-output build: - docker build --pull . -t $(IMAGE):$(TAG) +ifndef name + $(error No name was informed throught the "name" parameter) +endif + docker run --rm \ + `cat config.json | \ + jq '.[]|select(.name == "$(name)")|to_entries|map(select(.key != "variations"))' | \ + jq '.|map(" -e DOCKER_BUILD_" + (.key|ascii_upcase) + "=" + (.value|tostring) + "")|.[]' \ + --raw-output` \ + -v `pwd`:/work -w /work \ + webdevops/go-replace:latest \ + --mode=template ./`cat config.json | \ + jq '.[]|select(.name == "$(name)")|.template|if . == null then "Dockerfile.tmpl" else . end' --raw-output` \ + -o Dockerfile + docker build . --pull -t $(IMAGE):$(name) + rm Dockerfile push: build docker push $(IMAGE):$(TAG) +build-var: +ifndef name + $(error No variation was informed throught the "var" parameter) +endif + make build name=$(name) + docker build --build-arg IMAGE_BASE=$(IMAGE):$(name) --file Dockerfile.$(var) -t $(IMAGE):$(name)-$(var) . + +push-var: build-var + docker push $(IMAGE):$(TAG)-$(var) diff --git a/bin/swoole-run b/bin/swoole-run new file mode 100755 index 0000000..1ecc0b1 --- /dev/null +++ b/bin/swoole-run @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +server-warmup + +exec /usr/local/bin/php ./server.php diff --git a/config.json b/config.json new file mode 100644 index 0000000..d46273c --- /dev/null +++ b/config.json @@ -0,0 +1,58 @@ +[ + { + "name": "php7dot4", + "version": "7.4", + "base": "php:7.4-apache", + "xdebug_version": "3.1.6", + "redis_version": "5.3.7", + "imap_version": "", + "imap_type": "php-ext", + "php_errors_enabled": false, + "variations": ["pgsql"] + }, + { + "name": "php8dot2", + "version": "8.2", + "base": "php:8.2-apache-bookworm", + "xdebug_version": "3.2.1", + "redis_version": "5.3.7", + "imap_version": "", + "imap_type": "php-ext", + "php_errors_enabled": true, + "variations": [] + }, + { + "name": "php8dot3", + "version": "8.3", + "base": "php:8.3-apache-bookworm", + "xdebug_version": "3.3.2", + "redis_version": "5.3.7", + "imap_version": "", + "imap_type": "php-ext", + "php_errors_enabled": true, + "variations": ["grpc", "mongodb", "mongodb-1.21.0"] + }, + { + "name": "php8dot3-swoole", + "version": "8.3", + "base": "php:8.3-bookworm", + "template": "Dockerfile.swoole.tmpl", + "xdebug_version": "3.3.2", + "redis_version": "5.3.7", + "imap_version": "", + "imap_type": "php-ext", + "php_errors_enabled": true, + "variations": ["grpc"] + }, + { + "name": "php8dot4", + "version": "8.4", + "base": "php:8.4-apache-bookworm", + "xdebug_version": "3.4.1", + "redis_version": "6.1.0", + "imap_version": "", + "imap_type": "pecl", + "php_errors_enabled": true, + "variations": ["grpc", "mongodb"] + } +]