Skip to content

Docker Build & Push #1170

Docker Build & Push

Docker Build & Push #1170

Workflow file for this run

name: Docker Build & Push
on:
push:
branches: [ master, main ]
tags: [ 'v*' ]
pull_request:
branches: [ master, main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
# Shared base image (OS packages + PHP + compiled Swoole/UV + Composer).
BASE_IMAGE: ghcr.io/detain/phlix-base
jobs:
# --------------------------------------------------------------------------
# Shared base image. Carries the slow-to-build layers (OS packages, PHP, and
# the from-source Swoole + php-uv extensions) so the server and hub
# application images can FROM it without recompiling extensions every time
# their own Dockerfile changes. The compile layers are cached (GHA +
# registry), so when docker/Dockerfile.base is unchanged this job is a fast
# cache hit rather than a full recompile.
# --------------------------------------------------------------------------
docker-base:
name: Build and Push phlix-base
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to Container Registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push base image
uses: docker/build-push-action@v7
with:
context: .
file: docker/Dockerfile.base
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: |
${{ env.BASE_IMAGE }}:latest
${{ env.BASE_IMAGE }}:${{ github.sha }}
# Registry cache MUST use a dedicated tag, not the image tag — pushing
# `mode=max` cache to `:latest` pollutes the image manifest with a
# buildkit cacheconfig blob, which later breaks `FROM …:latest`
# ("unknown type application/vnd.buildkit.cacheconfig.v0").
cache-from: |
type=gha
type=registry,ref=${{ env.BASE_IMAGE }}:buildcache
cache-to: |
type=gha,mode=max
type=registry,ref=${{ env.BASE_IMAGE }}:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-args: |
PHP_VERSION=8.3
docker:
name: Build and Push phlix-server
runs-on: ubuntu-latest
needs: docker-base
permissions:
contents: read
packages: write
strategy:
matrix:
include:
- dockerfile: docker/Dockerfile
tag: latest
platform: linux/amd64,linux/arm64
- dockerfile: docker/Dockerfile.nvidia
tag: nvidia
platform: linux/amd64
- dockerfile: docker/Dockerfile.intel
tag: intel
platform: linux/amd64
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to Container Registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=
- name: Build and push
uses: docker/build-push-action@v7
with:
context: .
file: ${{ matrix.dockerfile }}
platforms: ${{ matrix.platform }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ matrix.tag }}
labels: ${{ steps.meta.outputs.labels }}
# Dedicated cache tag (not the image tag) — see the base job's note.
cache-from: type=gha,type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ matrix.tag }}
cache-to: type=gha,type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ matrix.tag }},mode=max,image-manifest=true,oci-mediatypes=true
build-args: |
PHP_VERSION=8.3
PHLIX_VERSION=${{ github.ref_name }}
PHLIX_BASE_IMAGE=${{ env.BASE_IMAGE }}:latest
# TODO: hub Dockerfile lives in detain/phlix-hub; ensure the workflow picks it up
# via the hub repo's release event. For now, this job clones the hub repo and
# builds from its Dockerfile so the structure exists. If detain/phlix-hub does
# not yet contain a Dockerfile, this job will fail loudly — that is intentional
# and the next PR (in the phlix-hub repo) should add it.
docker-hub:
name: Build and Push phlix-hub
runs-on: ubuntu-latest
needs: docker-base
permissions:
contents: read
packages: write
steps:
- name: Checkout phlix-hub repository
uses: actions/checkout@v6
with:
repository: detain/phlix-hub
ref: master
path: phlix-hub
- name: Verify hub Dockerfile exists
run: |
if [ ! -f phlix-hub/Dockerfile ]; then
echo "::error::phlix-hub/Dockerfile not found in detain/phlix-hub@master."
echo "Add a Dockerfile to the phlix-hub repo before this workflow can succeed."
exit 1
fi
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to Container Registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Compute hub image tags
id: hubmeta
run: |
SHA="${GITHUB_SHA::12}"
echo "tags=${{ env.REGISTRY }}/detain/phlix-hub:latest,${{ env.REGISTRY }}/detain/phlix-hub:${SHA}" >> "$GITHUB_OUTPUT"
- name: Build and push phlix-hub
uses: docker/build-push-action@v7
with:
context: phlix-hub
file: phlix-hub/Dockerfile
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.hubmeta.outputs.tags }}
# Dedicated cache tag (not the image tag) — see the base job's note.
cache-from: type=gha,type=registry,ref=${{ env.REGISTRY }}/detain/phlix-hub:buildcache
cache-to: type=gha,type=registry,ref=${{ env.REGISTRY }}/detain/phlix-hub:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-args: |
PHLIX_BASE_IMAGE=${{ env.BASE_IMAGE }}:latest