Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 97 additions & 19 deletions .github/workflows/build-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,22 @@ concurrency:

jobs:
build:
runs-on: ubuntu-24.04 # ubuntu-latest
name: Build ${{ matrix.target.platform }} ${{ matrix.variant }} ${{ matrix.php_version }}
runs-on: ${{ matrix.target.runner }}
timeout-minutes: 10

strategy:
fail-fast: false
matrix:
php_version: ['8.4', '8.3', '8.1', '8.0', '7.4']
php_version: ['8.5' , '8.4', '8.3', '8.1', '8.0', '7.4']
variant: ['apache', 'apache-chrome']
target:
- platform: linux/amd64
runner: ubuntu-24.04 # ubuntu-latest
artifact_suffix: linux-amd64
- platform: linux/arm64
runner: ubuntu-24.04-arm # ubuntu-latest
artifact_suffix: linux-arm64
exclude:
- php_version: '7.4'
variant: 'apache-chrome'
Expand All @@ -38,17 +47,13 @@ jobs:
- name: Checkout Code
uses: actions/checkout@v6

- name: Github Short SHA
run: |
echo "GITHUB_SHA_SHORT=$(echo $GITHUB_SHA | cut -c 1-7)" >> $GITHUB_ENV

- name: Set variables
run: |
if [ "${{ matrix.variant }}" == "apache" ]; then
echo "DOCKER_TAG=${{ matrix.php_version }}" >> $GITHUB_ENV
echo "DOCKER_TAG=${{ github.event.number }}_${{ matrix.php_version }}" >> $GITHUB_ENV
echo "DOCKER_FILE=Dockerfile" >> $GITHUB_ENV
elif [ "${{ matrix.variant }}" == "apache-chrome" ]; then
echo "DOCKER_TAG=${{ matrix.php_version }}-headless" >> $GITHUB_ENV
echo "DOCKER_TAG=${{ github.event.number }}_${{ matrix.php_version }}-headless" >> $GITHUB_ENV
echo "DOCKER_FILE=Dockerfile-headless" >> $GITHUB_ENV
else
echo "Invalid variant: ${{ matrix.variant }}"
Expand All @@ -58,21 +63,94 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4

- name: Login to Docker Registry
run: echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u ${{ secrets.DOCKER_HUB_USER }} --password-stdin

- name: Login to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin

- name: Build and push
- name: Build and push by digest
id: build
uses: docker/build-push-action@v7
with:
context: .
file: ./${{ matrix.php_version }}/${{ env.DOCKER_FILE }}
tags:
ghcr.io/${{ github.repository }}:${{ env.DOCKER_TAG }},
ghcr.io/${{ github.repository }}:${{ env.GITHUB_SHA_SHORT }}
push: true
platforms: linux/amd64,linux/arm64
file: ./aio/${{ env.DOCKER_FILE }}
build-args: |
PHP_VERSION=${{ matrix.php_version }}
platforms: ${{ matrix.target.platform }}
outputs: type=image,name=ghcr.io/${{ github.repository }},push-by-digest=true,name-canonical=true,push=true
provenance: mode=min
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Export digest
run: |
mkdir -p "/tmp/digests/${{ env.DOCKER_TAG }}"
DIGEST="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${{ env.DOCKER_TAG }}/${DIGEST#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v7
with:
name: digests-${{ env.DOCKER_TAG }}-${{ matrix.target.artifact_suffix }}
path: /tmp/digests
if-no-files-found: error
retention-days: 1

manifest:
name: Create multi-arch manifests
runs-on: ubuntu-24.04-arm
timeout-minutes: 10
needs: build

steps:
- name: Github Short SHA
run: |
echo "GITHUB_SHA_SHORT=$(echo "$GITHUB_SHA" | cut -c 1-7)" >> "$GITHUB_ENV"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4

- name: Login to Docker Registry
run: echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u ${{ secrets.DOCKER_HUB_USER }} --password-stdin

- name: Login to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin

- name: Download digests
uses: actions/download-artifact@v8
with:
pattern: digests-*
path: /tmp/digests
merge-multiple: true

- name: Create multi-arch manifests
run: |
set -euo pipefail

for digest_dir in /tmp/digests/*; do
if [ ! -d "$digest_dir" ]; then
continue
fi

docker_tag="$(basename "$digest_dir")"
digest_count="$(find "$digest_dir" -maxdepth 1 -type f | wc -l | tr -d ' ')"

if [ "$digest_count" -lt 2 ]; then
echo "Expected at least 2 digests for ${docker_tag}, found ${digest_count}"
find "$digest_dir" -maxdepth 1 -type f -print
exit 1
fi

refs=""
for digest_file in "$digest_dir"/*; do
digest="$(basename "$digest_file")"
refs="${refs} ghcr.io/${{ github.repository }}@sha256:${digest}"
done

echo "Creating manifest for ghcr.io/${{ github.repository }}:${docker_tag}"

docker buildx imagetools create \
-t "ghcr.io/${{ github.repository }}:${docker_tag}" \
-t "ghcr.io/${{ github.repository }}:${GITHUB_SHA_SHORT}-${docker_tag}" \
${refs}

docker buildx imagetools inspect "ghcr.io/${{ github.repository }}:${docker_tag}"
done
78 changes: 78 additions & 0 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Test Build Images on PR

permissions:
contents: read

on:
workflow_dispatch: {}
pull_request:
types: [opened, synchronize]
paths-ignore:
- "README.md"
- "docker-compose.yml"
- "examples/**"
- ".run/**"
- ".circleci/**"

concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true

jobs:
build:
name: Build ${{ matrix.target.platform }} ${{ matrix.variant }} ${{ matrix.php_version }}
runs-on: ${{ matrix.target.runner }}
timeout-minutes: 10

strategy:
fail-fast: false
matrix:
php_version: ['8.5' , '8.4', '8.3', '8.1', '8.0', '7.4']
variant: ['apache', 'apache-chrome']
target:
- platform: linux/amd64
runner: ubuntu-24.04 # ubuntu-latest
artifact_suffix: linux-amd64
- platform: linux/arm64
runner: ubuntu-24.04-arm # ubuntu-latest
artifact_suffix: linux-arm64
exclude:
- php_version: '7.4'
variant: 'apache-chrome'

steps:
- name: Checkout Code
uses: actions/checkout@v6

- name: Set variables
run: |
if [ "${{ matrix.variant }}" == "apache" ]; then
echo "DOCKER_TAG=pr_${{ github.event.number }}_${{ matrix.php_version }}" >> $GITHUB_ENV
echo "DOCKER_FILE=Dockerfile" >> $GITHUB_ENV
elif [ "${{ matrix.variant }}" == "apache-chrome" ]; then
echo "DOCKER_TAG=pr_${{ github.event.number }}_${{ matrix.php_version }}-headless" >> $GITHUB_ENV
echo "DOCKER_FILE=Dockerfile-headless" >> $GITHUB_ENV
else
echo "Invalid variant: ${{ matrix.variant }}"
exit 1
fi

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4

- name: Login to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin

- name: Build and push by digest
id: build
uses: docker/build-push-action@v7
with:
context: .
file: ./aio/${{ env.DOCKER_FILE }}
build-args: |
PHP_VERSION=${{ matrix.php_version }}
platforms: ${{ matrix.target.platform }}
push: false
provenance: mode=min
cache-from: type=gha
cache-to: type=gha,mode=max
23 changes: 11 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@

## Why

The images formed from this repo is to help minimize the extra steps needed to get up and running with a PHP Image with apache to serve traffic. All docker images are built in a CI pipeline and run every 2 days to ensure all dependencies are up-to-date with the source they are installed from.
The images formed from this repo are to help minimize the extra steps needed to get up and running with a PHP Image with apache to serve traffic. All docker images are built in a CI pipeline and run every 2 days to ensure all dependencies are up to date with the source they are installed from.

After using this docker image in other pipelines I was able to cut build times down by 4-5 minutes per build.
After using this docker image in other pipelines, I was able to cut build times down by 4-5 minutes per build.

_Images built also support ARM/ARM64 architectures_

## Changes

This image is the PHP 7.4 (and 8.0, 8.1) packaged with the following changes:
- PHP (version 7.4 or 8.0)
This image is the PHP+Apache Image packaged with the following changes:
- PHP (version 7.4 or 8.0–8.5)
- Apache
- OPCache (and configured)
- OPCache (configured)
- OpenSSL
- ZIP (with libzip-dev and php extension)
- git
- iputils
- Redis Extension
- GD and imagick Extensions
- PDO
Expand All @@ -25,15 +25,16 @@ This image is the PHP 7.4 (and 8.0, 8.1) packaged with the following changes:
- Apache Signatures Off
- Apache Allow htaccess overrides
- Apache Logs Updated to include the remote ips
- Apache Server Status (configured on :8282/healthz and :8282/server-status)

---

# Images

## [Github Images](https://github.com/nhalstead/php-apache-core/pkgs/container/php-apache-core)
## [GitHub Images](https://github.com/nhalstead/php-apache-core/pkgs/container/php-apache-core)

> ghcr.io/nhalstead/php-apache-core
> #### Automatically built on Wednesday
> #### Automatically built on Wednesday by GitHub Actions

| PHP Version | Tag: Apache | Tag: Apache + Chrome |
|:------------|:------------|:---------------------|
Expand All @@ -46,13 +47,11 @@ This image is the PHP 7.4 (and 8.0, 8.1) packaged with the following changes:
## [Docker Hub Images](https://hub.docker.com/r/nhalstead00/php-apache-core)

> nhalstead00/php-apache-core
> #### Automatically built every 2 days
> #### Automatically built every 2 days by CircleCI (will be replaced with GitHub Actions in the future)

| PHP Version | Tag: Apache | Tag: Apache + Chrome |
|:------------|:------------|:---------------------|
| 8.3 | 8.3-latest | 8.3-headless-latest |
| 8.1 | 8.1-latest | 8.1-headless-latest |
| 8.0 | 8.0-latest | 8.0-headless-latest |
| 7.4 | 7.4-latest | |


51 changes: 51 additions & 0 deletions aio/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Normal Operations for setup of Apache and ENV Vars
# Allow building different PHP versions from build args (CI uses PHP_VERSION)
ARG PHP_VERSION=8.3
ARG PHP_TAG=${PHP_VERSION}-apache
FROM php:${PHP_TAG} AS base

# Configure OPCache
ENV PHP_OPCACHE_VALIDATE_TIMESTAMPS=0
ENV PHP_OPCACHE_MAX_ACCELERATED_FILES=10000
ENV PHP_OPCACHE_MEMORY_CONSUMPTION=192
ENV PHP_OPCACHE_MAX_WASTED_PERCENTAGE=10

COPY common/opcache.ini /usr/local/etc/php/conf.d/opcache.ini

RUN apt-get update -y; \
apt-get install -y openssl zip unzip curl libpng-dev libzip-dev libmagickwand-dev --no-install-recommends; \
docker-php-ext-install -j"$(nproc)" gd zip pdo mysqli pdo_mysql opcache; \
pecl install redis imagick; \
docker-php-ext-enable -j"$(nproc)" redis imagick; \
apt autoremove -y; \
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \
rm -rf /var/lib/apt/lists/*;

FROM base

# Configure Apache: combine multiple small RUNs into one layer to reduce image size
# Copy scripts and config files first so they can be used in the same layer
COPY common/remoteip-env /usr/sbin
COPY common/remoteip-clear /usr/sbin
COPY common/opcache-preload /usr/sbin
COPY common/opcache-status /usr/sbin
COPY common/apache-status /usr/sbin
COPY common/status.conf /etc/apache2/sites-enabled/000-status.conf
COPY common/healthz.html /var/www/html/healthz.html

RUN set -eux; \
a2enmod rewrite remoteip status; \
touch /etc/apache2/conf-available/remoteip.conf; \
ln -s /etc/apache2/conf-available/remoteip.conf /etc/apache2/conf-enabled/remoteip.conf || true; \
chmod +x /usr/sbin/remoteip-* /usr/sbin/opcache-* /usr/sbin/apache-status || true; \
sed -ri -e 's!AllowOverride None!AllowOverride All!g' /etc/apache2/apache2.conf; \
sed -ri -e 's!Listen 80!Listen 8181!g' /etc/apache2/ports.conf; \
sed -ri -e 's!VirtualHost \*:80!VirtualHost \*:8181!g' /etc/apache2/sites-enabled/000-default.conf; \
echo "ServerSignature off" >> /etc/apache2/apache2.conf; \
echo "ServerTokens Prod" >> /etc/apache2/apache2.conf; \
printf '\n<IfModule mod_status.c>\n Listen 8282\n</IfModule>\n' >> /etc/apache2/ports.conf; \
sed -ri -e 's!#LoadModule remoteip_module!LoadModule remoteip_module!g' /etc/apache2/apache2.conf; \
sed -ri -e 's/LogFormat .* combined/LogFormat "%a %{c}a %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\" %I %O" combined/g' /etc/apache2/apache2.conf

EXPOSE 8181
EXPOSE 8282
Loading