ci(docker): fix latest/main publishing, add arm64 + GPU build check

Review fixes for the Docker packaging PR:

- docker-publish: tie the `latest` tag to pushes on `main` (the release
  branch). Previously it was gated on `is_default_branch`, but the
  default branch is `develop` and the workflow never ran there, so
  `latest` was never produced. main + `v*` tags publish; develop is
  validated via the pull_request trigger but does not publish.
- docker-publish: publish multi-arch amd64+arm64 (Apple Silicon / ARM)
  on real pushes via setup-qemu-action; PRs stay amd64-only for speed.
- docker-publish: only export the GHA cache on in-repo events (fork PRs
  get a read-only cache, which just emits 403 noise).
- docker-publish: add a build-only job that validates Dockerfile.gpu
  compiles so the CUDA variant can't silently rot.
- Dockerfile: correct the persistence comment — the default `minilm`
  model caches under ~/.cache/chroma (ChromaDB S3), not
  ~/.cache/huggingface (that's the optional embeddinggemma model).
- docker-compose: drop the redundant MEMPALACE_PALACE_PATH override (it
  duplicated the HOME=/data default); document overrides as examples.
This commit is contained in:
Igor Lins e Silva 2026-06-05 21:46:37 -03:00
parent 8757ba2650
commit eb3ff2e61a
3 changed files with 48 additions and 10 deletions

View File

@ -2,6 +2,9 @@ name: Docker
on: on:
push: push:
# `main` is the release branch: pushes here publish the released image and
# update `latest`; `v*` tags publish versioned images. develop does not
# publish — it is validated via the pull_request trigger below.
branches: [main] branches: [main]
tags: ["v*"] tags: ["v*"]
pull_request: pull_request:
@ -21,6 +24,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
# Needed for the emulated linux/arm64 build on real pushes.
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
@ -40,22 +47,49 @@ jobs:
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
with: with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# latest -> default branch; semver tags -> released versions. # latest -> main (the latest release); semver tags -> released versions.
tags: | tags: |
type=ref,event=branch type=ref,event=branch
type=ref,event=pr type=ref,event=pr
type=semver,pattern={{version}} type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable={{is_default_branch}} type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile
platforms: linux/amd64 # Publish multi-arch (amd64 + arm64 for Apple Silicon / ARM hosts) on
# real pushes; keep PRs amd64-only so the emulated arm64 build does not
# slow the PR check.
platforms: ${{ github.event_name != 'pull_request' && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max # Fork PRs get a read-only Actions cache, so writing it just emits 403
# noise — only export cache on in-repo events.
cache-to: ${{ github.event_name != 'pull_request' && 'type=gha,mode=max' || '' }}
# Build-only validation for the CUDA image so it cannot silently rot (CUDA base
# tag drift, cross-stage interpreter/venv copy paths, the `gpu` extra). The
# runner has no GPU, so this only proves the image *compiles*; it is never
# published (users build it themselves, per the README).
build-gpu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build GPU image (validation only — not published)
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.gpu
platforms: linux/amd64
push: false
cache-from: type=gha,scope=gpu
cache-to: ${{ github.event_name != 'pull_request' && 'type=gha,mode=max,scope=gpu' || '' }}

View File

@ -73,9 +73,11 @@ LABEL org.opencontainers.image.title="MemPalace" \
org.opencontainers.image.licenses="MIT" org.opencontainers.image.licenses="MIT"
# /data is the single persistence root: HOME points here, so the palace # /data is the single persistence root: HOME points here, so the palace
# (~/.mempalace/palace), config (~/.mempalace), and the HuggingFace model # (~/.mempalace/palace), config (~/.mempalace), and the embedding-model cache
# cache (~/.cache/huggingface, ~300 MB, lazy-downloaded on first use) all # all land under one mountable volume. The default `minilm` model caches under
# land under one mountable volume. # ~/.cache/chroma (~80 MB, from ChromaDB's S3); the optional `embeddinggemma`
# model caches under ~/.cache/huggingface (~300 MB). Both lazy-download on
# first use.
ENV HOME=/data \ ENV HOME=/data \
PATH="/app/.venv/bin:${PATH}" \ PATH="/app/.venv/bin:${PATH}" \
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \

View File

@ -22,9 +22,11 @@ services:
volumes: volumes:
- mempalace-data:/data - mempalace-data:/data
environment: environment:
# Override the palace location, embedding model, etc. here if needed. # Everything defaults correctly from HOME=/data (palace ->
# - MEMPALACE_EMBEDDING_MODEL=minilm # /data/.mempalace/palace, config -> /data/.mempalace, model cache ->
MEMPALACE_PALACE_PATH: /data/.mempalace/palace # /data/.cache). Override here only for non-default locations, e.g.:
# - MEMPALACE_EMBEDDING_MODEL=embeddinggemma # multilingual (default: minilm)
# - MEMPALACE_PALACE_PATH=/data/custom/palace
volumes: volumes:
mempalace-data: mempalace-data: