diff --git a/.github/workflows/publish-slic-docker-image.yml b/.github/workflows/publish-slic-docker-image.yml index 7bc5945..d4b0327 100644 --- a/.github/workflows/publish-slic-docker-image.yml +++ b/.github/workflows/publish-slic-docker-image.yml @@ -10,7 +10,7 @@ on: jobs: publish-slic-image: - runs-on: ubuntu-latest + runs-on: ${{ matrix.runner }} permissions: contents: read packages: write @@ -18,6 +18,15 @@ jobs: matrix: # The php_version is the docker tag from https://hub.docker.com/_/php/tags php_version: [ '7.3', '7.4', '8.0', '8.1', '8.2', '8.3' ] + arch: [ 'amd64', 'arm64' ] + # Add runner and platform info for each architecture + include: + - arch: amd64 + runner: ubuntu-latest + platform: linux/amd64 + - arch: arm64 + runner: ubuntu-24.04-arm + platform: linux/arm64 steps: - name: Checkout repository @@ -46,9 +55,8 @@ jobs: type=ref,event=branch type=ref,event=tag type=semver,pattern={{raw}} - - - name: Set up QEMU for multi-platform builds - uses: docker/setup-qemu-action@v3 + flavor: | + suffix=-${{ matrix.arch }},onlatest=true - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -61,11 +69,46 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - # Use the faster registry cache. - cache-from: type=registry,ref=ghcr.io/${{ github.repository }}/cache/slic-php${{ matrix.php_version }} - cache-to: type=registry,ref=ghcr.io/${{ github.repository }}/cache/slic-php${{ matrix.php_version }},mode=max + # Use the faster registry cache with platform-specific caching + cache-from: type=registry,ref=ghcr.io/${{ github.repository }}/cache/slic-php${{ matrix.php_version }}-${{ matrix.arch }} + cache-to: type=registry,ref=ghcr.io/${{ github.repository }}/cache/slic-php${{ matrix.php_version }}-${{ matrix.arch }},mode=max build-args: | PHP_VERSION=${{ matrix.php_version }} NODE_VERSION=18.17.0 NVM_VERSION=v0.40.1 - platforms: linux/amd64,linux/arm64 + platforms: ${{ matrix.platform }} + + create-slic-manifest: + needs: publish-slic-image + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + strategy: + matrix: + php_version: [ '7.3', '7.4', '8.0', '8.1', '8.2', '8.3' ] + steps: + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Create and push multi-arch manifest + run: | + # Determine the tag based on the event type + if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then + TAG="edge" + elif [[ "${{ github.ref }}" == refs/tags/* ]]; then + TAG="${GITHUB_REF#refs/tags/}" + else + TAG="${GITHUB_REF#refs/heads/}" + fi + + IMAGE_BASE="ghcr.io/${{ github.repository }}-php${{ matrix.php_version }}" + + # Create multi-arch manifest + docker buildx imagetools create -t "${IMAGE_BASE}:${TAG}" \ + "${IMAGE_BASE}:${TAG}-amd64" \ + "${IMAGE_BASE}:${TAG}-arm64" diff --git a/.github/workflows/publish-wordpress-docker-image.yml b/.github/workflows/publish-wordpress-docker-image.yml index 122e8ce..3d6d3a1 100644 --- a/.github/workflows/publish-wordpress-docker-image.yml +++ b/.github/workflows/publish-wordpress-docker-image.yml @@ -10,26 +10,77 @@ on: jobs: publish-wordpress-image: - runs-on: ubuntu-latest + runs-on: ${{ matrix.runner }} permissions: contents: read packages: write strategy: matrix: - wp_version: [ '6.2' ] - php_version: [ '8.0', '8.1', '8.2' ] include: - # No WordPress image for version 6.2+ and PHP 7.3: use the latest 5.9 version. - # This version is NOT updated in the containers/wordpress/Dockerfile for back-compatibility. + # WordPress 6.2 with PHP 8.0, 8.1, 8.2 - both architectures + - wp_version: '6.2' + php_version: '8.0' + runner: ubuntu-latest + platform: linux/amd64 + arch: amd64 + - wp_version: '6.2' + php_version: '8.0' + runner: ubuntu-24.04-arm + platform: linux/arm64 + arch: arm64 + - wp_version: '6.2' + php_version: '8.1' + runner: ubuntu-latest + platform: linux/amd64 + arch: amd64 + - wp_version: '6.2' + php_version: '8.1' + runner: ubuntu-24.04-arm + platform: linux/arm64 + arch: arm64 + - wp_version: '6.2' + php_version: '8.2' + runner: ubuntu-latest + platform: linux/amd64 + arch: amd64 + - wp_version: '6.2' + php_version: '8.2' + runner: ubuntu-24.04-arm + platform: linux/arm64 + arch: arm64 + # WordPress 5.9 with PHP 7.3 - both architectures + - wp_version: '5.9' + php_version: '7.3' + runner: ubuntu-latest + platform: linux/amd64 + arch: amd64 - wp_version: '5.9' php_version: '7.3' - # No WordPress image for version 6.2+ and PHP 7.4: use the latest 6.1.1 version. - # See containers/wordpress/Dockerfile for the wp-cli update to version 6.2. + runner: ubuntu-24.04-arm + platform: linux/arm64 + arch: arm64 + # WordPress 6.1.1 with PHP 7.4 - both architectures - wp_version: '6.1.1' php_version: '7.4' - # Use the latest 6.5 WordPress version for PHP 8.3. + runner: ubuntu-latest + platform: linux/amd64 + arch: amd64 + - wp_version: '6.1.1' + php_version: '7.4' + runner: ubuntu-24.04-arm + platform: linux/arm64 + arch: arm64 + # WordPress 6.5 with PHP 8.3 - both architectures + - wp_version: '6.5' + php_version: '8.3' + runner: ubuntu-latest + platform: linux/amd64 + arch: amd64 - wp_version: '6.5' php_version: '8.3' + runner: ubuntu-24.04-arm + platform: linux/arm64 + arch: arm64 steps: - name: Checkout repository @@ -58,9 +109,8 @@ jobs: type=ref,event=branch type=ref,event=tag type=semver,pattern={{raw}} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + flavor: | + suffix=-${{ matrix.arch }},onlatest=true - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -73,10 +123,52 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - # Use the faster registry cache. - cache-from: type=registry,ref=ghcr.io/${{ github.repository }}/cache/slic-wp-${{ matrix.wp_version }}-${{ matrix.php_version }} - cache-to: type=registry,ref=ghcr.io/${{ github.repository }}/cache/slic-wp-${{ matrix.wp_version }}-${{ matrix.php_version }},mode=max + # Use the faster registry cache with platform-specific caching + cache-from: type=registry,ref=ghcr.io/${{ github.repository }}/cache/slic-wp-${{ matrix.wp_version }}-${{ matrix.php_version }}-${{ matrix.arch }} + cache-to: type=registry,ref=ghcr.io/${{ github.repository }}/cache/slic-wp-${{ matrix.wp_version }}-${{ matrix.php_version }}-${{ matrix.arch }},mode=max build-args: | PHP_VERSION=${{ matrix.php_version }} WP_VERSION=${{ matrix.wp_version }} - platforms: linux/amd64,linux/arm64 + platforms: ${{ matrix.platform }} + + create-wordpress-manifest: + needs: publish-wordpress-image + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + strategy: + matrix: + # Match the unique combinations from the build matrix + include: + - php_version: '8.0' + - php_version: '8.1' + - php_version: '8.2' + - php_version: '7.3' + - php_version: '7.4' + - php_version: '8.3' + steps: + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Create and push multi-arch manifest + run: | + # Determine the tag based on the event type + if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then + TAG="edge" + elif [[ "${{ github.ref }}" == refs/tags/* ]]; then + TAG="${GITHUB_REF#refs/tags/}" + else + TAG="${GITHUB_REF#refs/heads/}" + fi + + IMAGE_BASE="ghcr.io/${{ github.repository }}-wordpress-php${{ matrix.php_version }}" + + # Create multi-arch manifest + docker buildx imagetools create -t "${IMAGE_BASE}:${TAG}" \ + "${IMAGE_BASE}:${TAG}-amd64" \ + "${IMAGE_BASE}:${TAG}-arm64" diff --git a/changelog.md b/changelog.md index a8dfd35..20d1bf6 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +# [2.1.2] - 2025-11-13 +- Change - GitHub Actions workflows now use native ARM64 runners (`ubuntu-24.04-arm`) instead of QEMU emulation for multi-platform builds, to reduce build times. +- Change - Optimized Dockerfile layer ordering to improve cache hit rates - local config files moved to end to prevent invalidating heavy system installation layers. +- Change - Added BuildKit cache mounts for apt package installation and PHP extension compilation, to reduce subsequent build times. +- Change - Added `IPE_CACHE_DIR` environment variable to cache PHP extension downloads and compiled artifacts across builds. +- Change - Implemented platform-specific registry caching (separate caches for amd64/arm64) to prevent cache conflicts and maximize reuse. + # [2.1.1] - 2025-11-04 - Change - Optimize docker builds and workflows for slic and WordPress containers. diff --git a/containers/slic/Dockerfile b/containers/slic/Dockerfile index e509342..8ba0bd6 100644 --- a/containers/slic/Dockerfile +++ b/containers/slic/Dockerfile @@ -13,6 +13,15 @@ ARG TARGETPLATFORM SHELL ["/bin/bash", "-eou", "pipefail", "-c"] +# ------------------------------- +# Environment variables +# ------------------------------- +# Disable AVIF for GD https://github.com/mlocati/docker-php-extension-installer#configuration +ENV IPE_GD_WITHOUTAVIF=${IPE_GD_WITHOUTAVIF} +ENV NVM_VERSION=${NVM_VERSION} +ENV NVM_DIR=/usr/local/bin/.nvm +ENV IPE_CACHE_DIR=/tmp/ipe-cache + # ------------------------------- # WP-CLI & PHP extension installer # ------------------------------- @@ -21,20 +30,19 @@ ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/do RUN chmod a+rx /usr/local/bin/wp /usr/local/bin/install-php-extensions -# Disable AVIF for GD https://github.com/mlocati/docker-php-extension-installer#configuration -ENV IPE_GD_WITHOUTAVIF=${IPE_GD_WITHOUTAVIF} -RUN install-php-extensions xdebug pdo pdo_mysql mysqli zip uopz pcntl sockets intl exif gd - # ------------------------------- -# NVM environment variables +# PHP extensions (heavy compilation step with cache mount) # ------------------------------- -ENV NVM_VERSION=${NVM_VERSION} -ENV NVM_DIR=/usr/local/bin/.nvm +RUN --mount=type=cache,target=/tmp/ipe-cache,sharing=locked \ + install-php-extensions xdebug pdo pdo_mysql mysqli zip uopz pcntl sockets intl exif gd # ------------------------------- -# Dependencies for NVM & general builds +# System dependencies (with cache mount for speed) # ------------------------------- -RUN apt-get update && \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + rm -f /etc/apt/apt.conf.d/docker-clean && \ + apt-get update && \ apt-get install -yqq --no-install-recommends \ ca-certificates curl git zip unzip iproute2 \ libnss3 libnspr4 libdbus-1-3 libatk1.0-0 libatk-bridge2.0-0 \ @@ -66,25 +74,7 @@ RUN set -eux; \ node -v; npm -v # ------------------------------- -# PHP uopz extension & XDebug -# ------------------------------- -COPY ./docker-php-ext-uopz.ini /usr/local/etc/php/conf.d/docker-php-ext-uopz.ini -COPY ./xdebug-on.sh /usr/local/bin/xdebug-on -COPY ./xdebug-off.sh /usr/local/bin/xdebug-off - -RUN chmod a+x /usr/local/bin/xdebug-on /usr/local/bin/xdebug-off && \ - chmod -R a+rwx /usr/local/etc/php/conf.d && xdebug-off - -# ------------------------------- -# Composer 1 & 2 -# ------------------------------- -COPY --from=composer1 /usr/bin/composer /usr/local/bin/composer1 -COPY --from=composer2 /usr/bin/composer /usr/local/bin/composer - -RUN chmod a+x /usr/local/bin/composer /usr/local/bin/composer1 - -# ------------------------------- -# Slic user & fixuid +# Slic user & fixuid setup # ------------------------------- RUN groupadd -g 1000 slic 2>/dev/null || true && \ useradd -u 1000 -g 1000 -m -s /bin/bash slic 2>/dev/null || true && \ @@ -95,22 +85,37 @@ RUN groupadd -g 1000 slic 2>/dev/null || true && \ esac && \ curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$FIXUID_ARCH.tar.gz \ | tar -C /usr/local/bin -xzf - && \ - chown root:root /usr/local/bin/fixuid && chmod 4755 /usr/local/bin/fixuid && \ + chown root:root /usr/local/bin/fixuid && \ + chmod 4755 /usr/local/bin/fixuid && \ mkdir -p /etc/fixuid +# ------------------------------- +# Composer 1 & 2 from multi-stage builds +# ------------------------------- +COPY --from=composer1 /usr/bin/composer /usr/local/bin/composer1 +COPY --from=composer2 /usr/bin/composer /usr/local/bin/composer + +# ------------------------------- +# Local config files (moved late for better caching) +# ------------------------------- +COPY ./docker-php-ext-uopz.ini /usr/local/etc/php/conf.d/docker-php-ext-uopz.ini +COPY ./xdebug-on.sh /usr/local/bin/xdebug-on +COPY ./xdebug-off.sh /usr/local/bin/xdebug-off COPY ./fixuid.yml /etc/fixuid/config.yml COPY ./.bashrc /home/slic/.bashrc COPY ./.bashrc /root/.bashrc COPY ./bashrc_scripts.sh /home/slic/bashrc_scripts.sh - -# Ensure NVM directory is owned by slic -RUN chown -R slic:slic $NVM_DIR +COPY ./slic-entrypoint.sh /usr/local/bin/slic-entrypoint.sh # ------------------------------- -# Entrypoint +# Final permissions & setup # ------------------------------- -COPY ./slic-entrypoint.sh /usr/local/bin/slic-entrypoint.sh -RUN chmod a+x /usr/local/bin/slic-entrypoint.sh +RUN chmod a+x /usr/local/bin/xdebug-on /usr/local/bin/xdebug-off \ + /usr/local/bin/composer /usr/local/bin/composer1 \ + /usr/local/bin/slic-entrypoint.sh && \ + chmod -R a+rwx /usr/local/etc/php/conf.d && \ + chown -R slic:slic $NVM_DIR && \ + xdebug-off ENTRYPOINT ["/usr/local/bin/slic-entrypoint.sh"] diff --git a/containers/wordpress/Dockerfile b/containers/wordpress/Dockerfile index 9beb80b..27c0a87 100644 --- a/containers/wordpress/Dockerfile +++ b/containers/wordpress/Dockerfile @@ -4,26 +4,44 @@ ARG WP_VERSION=6.1 FROM wordpress:${WP_VERSION}-php${PHP_VERSION}-apache -# Add all remote tools in one layer. +# ------------------------------- +# Environment variables +# ------------------------------- +ENV IPE_CACHE_DIR=/tmp/ipe-cache + +# ------------------------------- +# WP-CLI & PHP extension installer +# ------------------------------- ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/ ADD https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar /usr/local/bin/wp -# Consolidate chmod and the slow xdebug install into one layer to make cacheable. -RUN chmod a+x /usr/local/bin/install-php-extensions && \ +# ------------------------------- +# PHP extensions (with cache mount) +# ------------------------------- +RUN --mount=type=cache,target=/tmp/ipe-cache,sharing=locked \ + chmod a+x /usr/local/bin/install-php-extensions && \ chmod a+rx /usr/local/bin/wp && \ install-php-extensions xdebug -COPY xdebug-on.sh /usr/local/bin/xdebug-on -COPY xdebug-off.sh /usr/local/bin/xdebug-off - -# Consolidate all xdebug configuration and permissions into one layer. -RUN chmod a+x /usr/local/bin/xdebug-on /usr/local/bin/xdebug-off && \ - xdebug-off && \ - chmod -R a+rwx /usr/local/etc/php/conf.d - +# ------------------------------- +# WordPress version update (PHP 7.4) +# ------------------------------- # No image for WordPress 6.2+ is available for PHP 7.4. # If PHP_VERSION is 7.4, update WordPress to 6.2 using wp-cli. -# This layer is kept separate as it's conditional and should run last. +# This runs before COPY so changes to scripts don't invalidate this layer. RUN if echo "${PHP_VERSION}" | grep -q '^7.4'; then \ wp --allow-root --path=/usr/src/wordpress core download --version=6.2 --force; \ fi + +# ------------------------------- +# Local config files (moved late for better caching) +# ------------------------------- +COPY xdebug-on.sh /usr/local/bin/xdebug-on +COPY xdebug-off.sh /usr/local/bin/xdebug-off + +# ------------------------------- +# Final permissions & setup +# ------------------------------- +RUN chmod a+x /usr/local/bin/xdebug-on /usr/local/bin/xdebug-off && \ + chmod -R a+rwx /usr/local/etc/php/conf.d && \ + xdebug-off diff --git a/slic.php b/slic.php index 667df87..f2fcb0a 100644 --- a/slic.php +++ b/slic.php @@ -34,7 +34,7 @@ ] ); $cli_name = 'slic'; -const CLI_VERSION = '2.1.1'; +const CLI_VERSION = '2.1.2'; // If the run-time option `-q`, for "quiet", is specified, then do not print the header. if ( in_array( '-q', $argv, true ) || ( in_array( 'exec', $argv, true ) && ! in_array( 'help', $argv, true ) ) ) {