docs(docker): Hub pages for aio + ml, and the image table in the README
picpeak/ml has an empty Hub overview and picpeak/aio has none at all,
while backend and frontend carry hand-written ones — so the two newest
images are the two with nothing on their registry page.
Adds .github/dockerhub/{aio,ml}.md as the source of those pages and a
dockerhub-descriptions job that pushes them on every main merge, so the
page cannot drift from the release it describes. backend/frontend stay
hand-maintained for now: capturing their current Hub text into files is
a prerequisite, not a side effect of this change.
README gains a registry table for all four images (both registries share
digests and tags), the org-move callout lists the full set, and the
feature list finally mentions People in this gallery, which shipped in
#1074 without a README line.
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
# picpeak — All-in-one
|
||||
|
||||
**picpeak** is an open-source, self-hosted **photo-sharing platform for photographers**, with an optional CRM / accounting suite. This image is the **all-in-one** build: the backend, the built web UI and SQLite in **one container, one process** — no compose file, no separate database, no reverse proxy to wire up.
|
||||
|
||||
- 📦 **Source, docs & issues:** https://github.com/PicPeak/picpeak
|
||||
- 🧩 **Multi-container images:** [`picpeak/backend`](https://hub.docker.com/r/picpeak/backend) + [`picpeak/frontend`](https://hub.docker.com/r/picpeak/frontend)
|
||||
|
||||
## Supported tags
|
||||
- `latest` / `stable` — latest stable release
|
||||
- `x.y.z` — a pinned release (**recommended for production**)
|
||||
- `beta` / `main` — latest build from `main` (may be unstable)
|
||||
- **Architectures:** `linux/amd64`, `linux/arm64` (x86 and ARM NAS)
|
||||
|
||||
## Quick start
|
||||
|
||||
docker run -d --name picpeak -p 3000:3000 \
|
||||
-v picpeak:/data \
|
||||
-e JWT_SECRET="$(openssl rand -base64 48)" \
|
||||
picpeak/aio:stable
|
||||
|
||||
Then open **http://localhost:3000/admin** and complete the setup wizard. Read the one-time setup token with:
|
||||
|
||||
docker exec picpeak cat /data/db/SETUP_TOKEN
|
||||
|
||||
> 🔗 Share links need to know your address. The image defaults `FRONTEND_URL` to `http://localhost:3000`; pass `-e FRONTEND_URL=https://photos.example.com` (or set the site URL in Settings) before you send a gallery to a client.
|
||||
|
||||
## Ports & volumes
|
||||
- Container port **3000** (HTTP; put your own TLS terminator in front for public use).
|
||||
- **One volume: `/data`** — back it up and you have backed up the install.
|
||||
- `/data/db` — `picpeak.db` and `SETUP_TOKEN`
|
||||
- `/data/storage` — originals, thumbnails, archives
|
||||
- `/data/logs`, `/data/backup`
|
||||
|
||||
## External Postgres
|
||||
SQLite is this image's default, not its only option. Point it at an existing database exactly like the backend image:
|
||||
|
||||
-e DATABASE_CLIENT=pg -e DB_HOST=… -e DB_USER=… -e DB_PASSWORD=…
|
||||
|
||||
## How it differs from the compose stack
|
||||
- **SQLite takes one writer at a time** — right for a home server, a NAS or a single studio; the compose stack with PostgreSQL is what scales.
|
||||
- **No Redis** — background jobs run in-process.
|
||||
- **Face recognition is unavailable** here. It needs the separate [`picpeak/ml`](https://hub.docker.com/r/picpeak/ml) sidecar, and a second image-processing pipeline competing with thumbnailing for one container's CPU would just make the install slow. Run the multi-container deployment for that feature.
|
||||
|
||||
You can move to the full stack later without reinstalling: take a `.picpeak` backup and restore it there.
|
||||
|
||||
## Docs
|
||||
Volume layout, the external-Postgres variant, TLS, updates and the limits: **https://docs.picpeak.app/deployment/single-container**
|
||||
@@ -0,0 +1,56 @@
|
||||
# picpeak — ML sidecar (face detection)
|
||||
|
||||
**picpeak** is an open-source, self-hosted **photo-sharing platform for photographers**. This image is the **optional face-detection sidecar**: it detects faces in one image and returns a bounding box, five landmarks, quality signals and a 512-d embedding per face.
|
||||
|
||||
**Nothing else.** No database, no volumes, no state, no egress, no model download at runtime. Clustering, person identity, thresholds and every privacy decision live in the picpeak backend, where the data already is — this service forgets each image the moment it answers.
|
||||
|
||||
If you don't run this container, the feature does not exist.
|
||||
|
||||
- 📦 **Source, docs & issues:** https://github.com/PicPeak/picpeak
|
||||
- 🧩 **Runs with:** [`picpeak/backend`](https://hub.docker.com/r/picpeak/backend) + [`picpeak/frontend`](https://hub.docker.com/r/picpeak/frontend)
|
||||
|
||||
## Supported tags
|
||||
- `latest` / `stable` — latest stable release
|
||||
- `x.y.z` — a pinned release (**recommended for production** — keep it on the **same** tag as the backend)
|
||||
- `beta` / `main` — latest build from `main` (may be unstable)
|
||||
- **Architectures:** `linux/amd64`, `linux/arm64`
|
||||
|
||||
> The sidecar's API contract is versioned with the backend that calls it, so `PICPEAK_CHANNEL` resolves the same string across all picpeak images.
|
||||
|
||||
## Turning it on
|
||||
The maintained compose file already contains this service behind a profile — you do not write it by hand:
|
||||
|
||||
docker compose --profile faces up -d
|
||||
|
||||
Then two deliberate actions in the app, neither of which is installing this container:
|
||||
|
||||
1. Enable the **`faces`** feature flag in admin settings.
|
||||
2. Enable **"Detect people in this gallery"** per event.
|
||||
|
||||
**Nothing in the backend touches this service while the flag is off**, so an install without this container never attempts a connection.
|
||||
|
||||
## Configuration
|
||||
| | |
|
||||
|---|---|
|
||||
| `FACE_ML_TOKEN` | **Required.** The container **refuses to start** without it, so an accidentally published port is never a free face-detection API. Must match the backend's `FACE_ML_TOKEN`. |
|
||||
| `FACE_ORT_THREADS` | ONNX Runtime threads (default `1`). |
|
||||
|
||||
Port **8000**, no volumes, no published ports needed — the backend reaches it on the compose network. `FACE_ML_URL` defaults to `http://picpeak-ml:8000` (the compose service name), so the standard deployment needs no URL configuration.
|
||||
|
||||
## API
|
||||
All endpoints except `/health` require the `X-Face-ML-Token` header.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| `GET /health` | `{"status": "ok"}` — unauthenticated, used by the healthcheck |
|
||||
| `GET /info` | `{detector, embedder, model_version, dim}` |
|
||||
| `POST /faces` | multipart `image` → `{model_version, faces: [...]}` |
|
||||
|
||||
## Models
|
||||
YuNet (detection) + FaceNet-512 (embedding), **both MIT**, baked into the image and verified by SHA-256 at build time — never downloaded at runtime, so airgapped installs work and a model cannot change under a running deployment. See [`ml/LICENSES.md`](https://github.com/PicPeak/picpeak/blob/main/ml/LICENSES.md) for why these and not InsightFace's non-commercial weights.
|
||||
|
||||
## Not available on the all-in-one image
|
||||
[`picpeak/aio`](https://hub.docker.com/r/picpeak/aio) sets `PICPEAK_SINGLE_CONTAINER=true` and the backend refuses to enable face recognition there — a second image-processing pipeline competing with thumbnailing for one small container's CPU would not fail loudly, it would just make the install slow. Run the multi-container deployment for this feature.
|
||||
|
||||
## Docs
|
||||
**https://docs.picpeak.app** · sidecar internals, model conversion and the alignment/threshold contract: [`ml/README.md`](https://github.com/PicPeak/picpeak/blob/main/ml/README.md)
|
||||
@@ -1,6 +1,6 @@
|
||||
# Docker Build and Push Workflow
|
||||
|
||||
This GitHub Actions workflow automatically builds and pushes Docker images for the backend, the frontend, and the all-in-one image to GitHub Container Registry (ghcr.io).
|
||||
This GitHub Actions workflow automatically builds and pushes Docker images for the backend, the frontend, the all-in-one image and the optional ML sidecar to GitHub Container Registry (ghcr.io). On the canonical org repo every one of them is mirrored to Docker Hub as `docker.io/picpeak/{backend,frontend,aio,ml}`; forks build the same images GHCR-only.
|
||||
|
||||
The **all-in-one image** (`<repo>/aio`, built from `Dockerfile.aio` at the repo root, #1042) bundles the backend and the built frontend into a single container with SQLite as the default engine — one `docker run`, no compose. It follows the same per-arch build → digest-merge → per-version tag scheme as the other two images, is mirrored to Docker Hub (`docker.io/picpeak/aio`) alongside GHCR on the canonical org repo, and every PR additionally runs a `smoke-aio` job that boots the image and asserts the SPA shell, brand-title rendering, immutable asset caching, and the SQLite engine resolution.
|
||||
|
||||
@@ -12,6 +12,7 @@ The **all-in-one image** (`<repo>/aio`, built from `Dockerfile.aio` at the repo
|
||||
- 🔒 **Security scanning** with Trivy vulnerability scanner
|
||||
- 💾 **Build caching** for faster subsequent builds
|
||||
- 📊 **Build summaries** in GitHub Actions UI
|
||||
- 📝 **Docker Hub pages** for `aio` and `ml` synced from `.github/dockerhub/*.md` on every `main` merge (`dockerhub-descriptions` job). `backend` and `frontend` pages are still hand-maintained in the Hub UI — add `.github/dockerhub/{backend,frontend}.md` with their current text before putting them under the same job.
|
||||
|
||||
## Authentication
|
||||
|
||||
@@ -54,6 +55,11 @@ docker pull ghcr.io/picpeak/picpeak/backend:v1.0.0
|
||||
|
||||
# Pull for specific architecture
|
||||
docker pull --platform linux/arm64 ghcr.io/picpeak/picpeak/backend:latest
|
||||
|
||||
# The same images on Docker Hub (identical tags, identical digests)
|
||||
docker pull picpeak/backend:latest
|
||||
docker pull picpeak/aio:stable
|
||||
docker pull picpeak/ml:stable
|
||||
```
|
||||
|
||||
### Using in Docker Compose
|
||||
|
||||
@@ -1306,6 +1306,53 @@ jobs:
|
||||
run: |
|
||||
docker buildx imagetools inspect docker.io/picpeak/ml:${{ steps.meta-ml.outputs.version }}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Docker Hub repository pages
|
||||
# ---------------------------------------------------------------------------
|
||||
# The Hub overview for an image is repository metadata, not part of the
|
||||
# manifest, so pushing tags never updates it. Keep the copy for the two
|
||||
# newest images in-repo and push it from CI, so a Hub visitor is never
|
||||
# reading a page that describes a release from six months ago.
|
||||
#
|
||||
# Scope: aio and ml only. picpeak/{backend,frontend} still have their pages
|
||||
# maintained by hand in the Hub UI — bring them under this job by adding
|
||||
# .github/dockerhub/{backend,frontend}.md with the current text first,
|
||||
# otherwise this would overwrite them with a near-copy.
|
||||
#
|
||||
# Only on `main` pushes for the canonical org repo: descriptions are
|
||||
# per-repository, not per-tag, so once per merge is exactly enough.
|
||||
dockerhub-descriptions:
|
||||
needs: [merge-aio, merge-ml]
|
||||
if: always() && github.repository == 'PicPeak/picpeak' && github.ref == 'refs/heads/main' && needs.merge-aio.result == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Update picpeak/aio description
|
||||
uses: peter-evans/dockerhub-description@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
repository: picpeak/aio
|
||||
short-description: "picpeak all-in-one — self-hosted photo sharing + CRM in a single container (SQLite)."
|
||||
readme-filepath: .github/dockerhub/aio.md
|
||||
|
||||
# Skipped whenever the sidecar itself was skipped (FACENET_ONNX_URL unset),
|
||||
# since the Hub repository only exists once something has been pushed to it.
|
||||
- name: Update picpeak/ml description
|
||||
if: needs.merge-ml.result == 'success'
|
||||
uses: peter-evans/dockerhub-description@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
repository: picpeak/ml
|
||||
short-description: "picpeak face-detection sidecar — optional and stateless. Pairs with picpeak/backend."
|
||||
readme-filepath: .github/dockerhub/ml.md
|
||||
|
||||
summary:
|
||||
needs: [build-backend, merge-backend, build-frontend, merge-frontend, build-aio, merge-aio, smoke-aio, build-ml, merge-ml]
|
||||
if: always()
|
||||
|
||||
Reference in New Issue
Block a user