diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index da41c7140..9a5dd47cd 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,10 +1,8 @@ name: ci / docker publish # Build the Odysseus image and publish to GHCR. -# push to main -> :latest, :X.Y.Z, :X.Y.Z- (curated release; main is fast-forwarded at releases; -# :X.Y.Z- is an immutable, traceable prod pin — APP_VERSION may -# not move between builds, so the bare :X.Y.Z tag alone is mutable) -# push to dev -> :dev, :X.Y.Z-dev. (rolling dev + an immutable, traceable pin) +# push to main -> :latest, :X.Y.Z (curated release; main is fast-forwarded at releases) +# push to dev -> :dev, :X.Y.Z-dev. (rolling dev + an immutable, traceable pin) # Multi-arch (linux/amd64 + linux/arm64): each arch builds on its own native # runner and pushes by digest, then a merge job stitches the digests into one # manifest list and applies the tags (faster + cleaner than QEMU emulation). @@ -122,7 +120,6 @@ jobs: tags: | type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} type=raw,value=${{ steps.ver.outputs.version }},enable=${{ github.ref == 'refs/heads/main' }} - type=raw,value=${{ steps.ver.outputs.version }}-${{ steps.ver.outputs.short }},enable=${{ github.ref == 'refs/heads/main' }} type=raw,value=dev,enable=${{ github.ref == 'refs/heads/dev' }} type=raw,value=${{ steps.ver.outputs.version }}-dev.${{ steps.ver.outputs.short }},enable=${{ github.ref == 'refs/heads/dev' }} - name: Create manifest list + push tags @@ -138,16 +135,8 @@ jobs: IMAGE_NAME: ${{ env.IMAGE_NAME }} - name: Inspect run: | - # main: verify both the mutable :latest and the immutable :X.Y.Z- prod pin - # actually resolved in the registry; dev: verify :dev. - if [ "$GITHUB_REF" = "refs/heads/main" ]; then - refs=("latest" "${{ steps.ver.outputs.version }}-${{ steps.ver.outputs.short }}") - else - refs=("dev") - fi - for ref in "${refs[@]}"; do - docker buildx imagetools inspect "${REGISTRY}/${IMAGE_NAME}:${ref}" - done + if [ "$GITHUB_REF" = "refs/heads/main" ]; then ref=latest; else ref=dev; fi + docker buildx imagetools inspect "${REGISTRY}/${IMAGE_NAME}:${ref}" env: REGISTRY: ${{ env.REGISTRY }} IMAGE_NAME: ${{ env.IMAGE_NAME }} diff --git a/README.md b/README.md index ea3a276c3..72bd1303c 100644 --- a/README.md +++ b/README.md @@ -36,14 +36,6 @@ docker compose up -d --build Open `http://localhost:7000` when the containers are healthy. The first admin password is printed in `docker compose logs odysseus`. -The compose files pull the official multi-arch image `ghcr.io/odysseus-dev/odysseus` (published by CI on every push to `main` and `dev`) and only build locally if the pull fails — so this also works on hosts without a build toolchain, e.g. as a [Portainer](https://www.portainer.io/) stack. - -**Production deployments:** pin the immutable tag instead of `:latest`. `:latest` and bare `:X.Y.Z` tags move on every push to `main`, but `:X.Y.Z-` (e.g. `1.0.2-7c8070f`) always refers to one specific build: - -```bash -ODYSSEUS_IMAGE=ghcr.io/odysseus-dev/odysseus:1.0.2-7c8070f docker compose up -d -``` - Native installs, GPU notes, Windows/macOS instructions, HTTPS, and configuration live in the [setup guide](website/setup.md). ## Features diff --git a/docker-compose.gpu-amd.yml b/docker-compose.gpu-amd.yml index 92420a013..8d0cf1653 100644 --- a/docker-compose.gpu-amd.yml +++ b/docker-compose.gpu-amd.yml @@ -12,15 +12,6 @@ # host's numeric render group id when needed. See docker/gpu.amd.yml for details. services: odysseus: - # Official multi-arch GHCR image (linux/amd64 + linux/arm64), published by - # the "ci / docker publish" workflow on every push to main and dev. - # Docker pulls this image when it is reachable, and only falls back to the - # local build below when the pull fails (e.g. no network on the host), so - # hosts without a build toolchain (Portainer stacks, etc.) get the - # registry build. For production, pin an immutable tag via ODYSSEUS_IMAGE - # - e.g. ghcr.io/odysseus-dev/odysseus:1.0.2-7c8070f (X.Y.Z-) - since - # :latest and bare :X.Y.Z tags move on every main push. - image: ${ODYSSEUS_IMAGE:-ghcr.io/odysseus-dev/odysseus:latest} build: . ports: - "${APP_BIND:-127.0.0.1}:${APP_PORT:-7000}:7000" diff --git a/docker-compose.gpu-nvidia.yml b/docker-compose.gpu-nvidia.yml index ad29aefd9..69331ffb6 100644 --- a/docker-compose.gpu-nvidia.yml +++ b/docker-compose.gpu-nvidia.yml @@ -11,15 +11,6 @@ # for setup details. services: odysseus: - # Official multi-arch GHCR image (linux/amd64 + linux/arm64), published by - # the "ci / docker publish" workflow on every push to main and dev. - # Docker pulls this image when it is reachable, and only falls back to the - # local build below when the pull fails (e.g. no network on the host), so - # hosts without a build toolchain (Portainer stacks, etc.) get the - # registry build. For production, pin an immutable tag via ODYSSEUS_IMAGE - # - e.g. ghcr.io/odysseus-dev/odysseus:1.0.2-7c8070f (X.Y.Z-) - since - # :latest and bare :X.Y.Z tags move on every main push. - image: ${ODYSSEUS_IMAGE:-ghcr.io/odysseus-dev/odysseus:latest} build: . ports: - "${APP_BIND:-127.0.0.1}:${APP_PORT:-7000}:7000" diff --git a/docker-compose.yml b/docker-compose.yml index 331a5a0c6..708e5df82 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,14 +1,5 @@ services: odysseus: - # Official multi-arch GHCR image (linux/amd64 + linux/arm64), published by - # the "ci / docker publish" workflow on every push to main and dev. - # Docker pulls this image when it is reachable, and only falls back to the - # local build below when the pull fails (e.g. no network on the host), so - # hosts without a build toolchain (Portainer stacks, etc.) get the - # registry build. For production, pin an immutable tag via ODYSSEUS_IMAGE - # — e.g. ghcr.io/odysseus-dev/odysseus:1.0.2-7c8070f (X.Y.Z-) — since - # :latest and bare :X.Y.Z tags move on every main push. - image: ${ODYSSEUS_IMAGE:-ghcr.io/odysseus-dev/odysseus:latest} build: . ports: - "${APP_BIND:-127.0.0.1}:${APP_PORT:-7000}:7000" diff --git a/website/setup.md b/website/setup.md index 2cf4d7b8c..aeaf6baf6 100644 --- a/website/setup.md +++ b/website/setup.md @@ -30,24 +30,6 @@ docker compose up -d --build ``` To include optional extras in the image (PDF viewer, Office extraction; includes AGPL PyMuPDF), build with `docker compose build --build-arg INSTALL_OPTIONAL=true` before `up`. -**Official Docker images.** The compose files reference the official multi-arch image `ghcr.io/odysseus-dev/odysseus`, which CI (the `ci / docker publish` workflow) publishes on every push to `main` and `dev`. When the image is reachable, Compose pulls it instead of building — so the same files work on hosts without a build toolchain (Portainer stacks, Coolify, etc.). `--build` forces a local build regardless. - -Tag scheme: - -| Tag | Meaning | -| --- | --- | -| `:latest`, `:X.Y.Z` | Latest curated build from `main`. **Mutable** — re-pushed on every push to `main`, even without a version bump. | -| `:X.Y.Z-` | Immutable build pin (e.g. `1.0.2-7c8070f`). One tag, one build, forever. **Use this in production.** | -| `:dev`, `:X.Y.Z-dev.` | Rolling `dev` branch builds; the `` form is also immutable. | - -For production, pin the immutable tag by overriding the image in `.env` (or the stack's environment variables): - -```bash -ODYSSEUS_IMAGE=ghcr.io/odysseus-dev/odysseus:1.0.2-7c8070f -``` - -Browse current tags at . (Until this package is made public and linked to the repo by an org owner, pulls fall back to the local build automatically — that fallback is intentional.) - Open `http://localhost:7000` when the containers are healthy. Docker Compose binds the web UI to `127.0.0.1` by default. If the port is taken, set `APP_PORT=7001` in `.env` and recreate the container. Set `APP_BIND=0.0.0.0`