Skip to content

Mirror the MinIO CI image to GHCR - #2

Merged
dbernstein merged 1 commit into
mainfrom
chore/minio-mirror-image
Sep 24, 2026
Merged

dbernstein merged 1 commit into
mainfrom
chore/minio-mirror-image

Conversation

@dbernstein

@dbernstein dbernstein commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Description

Adds a mirror of the upstream MinIO server image, published as
ghcr.io/thepalaceproject/palace-ci-minio:

  • images/minio/Dockerfile — assembles the image from MinIO's official GitHub release binaries
    (minio RELEASE.2025-09-07T16-13-09Z, mc RELEASE.2025-08-13T08-35-41Z) plus the AGPL
    license files, each pinned by sha256 via BuildKit's ADD --checksum.
  • .github/workflows/build-minio-mirror.yml — builds linux/amd64 + linux/arm64 and pushes to
    GHCR. Runs only when the Dockerfile or the workflow changes, or on demand.
  • A README section covering what the image is and how to consume it.

This lives in ci-scripts rather than circulation because the image is shared by three repos and
belongs to none of them in particular. GHCR packages are namespaced by org, not repo, so one mirror
serves all three. Supersedes ThePalaceProject/circulation#3766, which is now closed.

Design notes

  • Assembled from release binaries, not pulled and re-tagged. Both upstream registries are
    closed to anonymous pulls, so there is no image left to docker pull, and dl.min.io is gone
    too (410). GitHub release assets are the one channel MinIO still serves anonymously. The binaries
    are byte-for-byte identical to the ones inside the last upstream image CI used — verified below.
  • Bare passthrough, no Palace configuration. circulation and library-registry use one set of credentials, the library registry uses another. Baking any of that in would fork the image between repos
    immediately, so each repo keeps its own Dockerfile and changes only its FROM line.
  • Pinned to an immutable tag, no latest. Following a moving upstream tag is part of how we
    got here. RELEASE.2025-09-07T16-13-09Z is also the last MinIO release to publish binaries at
    all — later tags ship no assets — so there is no newer version to move to.
  • Only main publishes. Pull requests and workflow_dispatch runs from a branch build both
    architectures and verify the checksums, then discard the result. An unmerged branch must not be
    able to overwrite a tag three other repos pin their CI to.
  • Public visibility, consistent with circ-webapp, circ-scripts, circ-exec and
    circ-baseimage, so no docker login for developers and no package-access grants for CI.
  • palace- rather than circ- prefix, because the image is shared across three repos.

⚠️ One-time manual step after merge

GHCR packages are created private. Once the workflow has run, set palace-ci-minio to public
(Org → Packages → palace-ci-minio → Package settings). Until that is done, the three consumer PRs
will still fail.

Consumer PRs, all draft, each a single FROM line:
ThePalaceProject/circulation#3767, ThePalaceProject/library-registry#1066,
ThePalaceProject/virtual-library-card#1016.

Motivation and Context

All tox-docker CI jobs in circulation fail while building the MinIO test container, and the other
two repos will hit the same wall on their next run:

docker.errors.BuildError: unauthorized: access to the requested resource is not authorized

MinIO has progressively withdrawn public distribution — Docker Hub around 13 Sept (worked around in
ThePalaceProject/circulation#3728 by moving to quay.io), and quay.io around 24 Sept. Anonymous
probes on 24 Sept:

Probe Result
quay.io/minio/minio:latest manifest 401
quay.io/minio/minio:RELEASE.2024-01-16T16-07-38Z (pinned old tag) 401
registry-1.docker.io/minio/minio:latest manifest 401
Docker Hub API for minio/minio object not found
dl.min.io server/client binaries 410
quay.io/prometheus/busybox:latest (control) 200

Quay issues an anonymous pull token and then refuses the manifest, so the repository is gated rather
than the network; the control confirms anonymous pulls work from the same machine. Two consequences:
pinning a digest or an older tag will not help, because the whole repository is closed; and a local
cache will not help, because tox_docker passes pull=True on every build
(tox_docker/plugin.py), forcing a fresh pull. Local tox fails identically, so developers cannot
run the suites either.

Retirement

This mirror is a bridge, not a destination — the intent is to drop MinIO for a maintained
S3-compatible image. It should be short-lived for two reasons: we do not want to become a de-facto
public distributor of a frozen MinIO build; and GitHub does not allow self-service deletion of a
public package once any version exceeds 5,000 downloads, above which it becomes a Support request.
With pull=True on every build, ephemeral runners and three repos pulling, that threshold arrives
quickly.

When the time comes:

gh api -X DELETE /orgs/ThePalaceProject/packages/container/palace-ci-minio

How Has This Been Tested?

Verified locally on macOS / Docker 29.6.1 (arm64 host).

The mirrored artifacts are identical to the withdrawn upstream image. A cached copy of
quay.io/minio/minio:latest (labelled RELEASE.2025-09-07T16-13-09Z) was still present locally;
its binaries and license files hash the same as what the mirror downloads:

# inside the cached upstream image (arm64)          # published by MinIO on GitHub
5c83cd2c…f03d  /usr/bin/minio                        5c83cd2c…f03d  minio.linux-arm64.RELEASE.2025-09-07T16-13-09Z
14c8c961…c12c  /usr/bin/mc                           14c8c961…c12c  mc.linux-arm64.RELEASE.2025-08-13T08-35-41Z
0d96a4ff…bcb0  /licenses/LICENSE                     0d96a4ff…bcb0  minio/minio@RELEASE.2025-09-07T16-13-09Z:LICENSE
113b8c63…8542  /licenses/CREDITS                     113b8c63…8542  minio/minio@RELEASE.2025-09-07T16-13-09Z:CREDITS

Build. Builds for linux/amd64 and linux/arm64; both architectures' checksums verify (a
mismatch fails the build by design). The final stage has no RUN instructions, so it cross-builds
without QEMU — confirmed on a CI runner that advertised only linux/amd64…/386 as supported.

Runtime. minio --version and mc --version report the expected releases; the server comes up
and /minio/health/live returns 200 in ~3s; the console on :9001 returns 200; curl inside the
container returns 200 against the health endpoint (the check docker-compose.yml uses); and
mc alias set / mc mb / mc anonymous set download all succeed (the operations
virtual-library-card's entrypoint needs). /licenses/LICENSE and /licenses/CREDITS are present
and hash-identical to upstream's.

End-to-end through tox. Because pull=True rejects a local-only tag, the image was pushed to a
throwaway registry:2 on localhost and circulation's docker/Dockerfile.minio.ci temporarily
pointed at it, so the whole chain was exercised — tox building the consumer Dockerfile, pulling the
mirror from a real registry, starting the container and running the tests:

py312-docker: docker> build .../docker/Dockerfile.minio.ci target 'minio'
py312-docker: docker> run 'sha256:fe9e8121edcb' (from 'minio-circ')
py312-docker: commands[0]> pytest -m minio --no-cov -q
14 passed in 13.22s

The same local-registry substitution was used to build and run library-registry's
docker/Dockerfile.minio.ci (healthy, mc works) and virtual-library-card's ci/minio/Dockerfile
(entrypoint completes — bucket created, anonymous download policy set, anonymous bucket read returns
200).

🤖 Generated with Claude Code

MinIO has withdrawn anonymous public access to its server image: first from
Docker Hub (~13 Sept), then from quay.io (~24 Sept). Both registries now answer
401 to anonymous manifest requests for every tag, and dl.min.io answers 410. Any
Dockerfile doing `FROM <registry>/minio/minio` fails before tests run, which is
every tox-docker job in circulation, library-registry and virtual-library-card.

Pinning an older tag does not help (the whole repository is gated, not just
:latest), and neither does a local cache (tox_docker passes pull=True on every
build, forcing a fresh pull).

This adds a mirror published as ghcr.io/thepalaceproject/palace-ci-minio, built
from MinIO's GitHub release assets, the one channel still served anonymously.
Every artifact is pinned by sha256, and the binaries are byte-for-byte identical
to the ones inside the last upstream image CI used, verified by comparing their
sha256 against /usr/bin/minio and /usr/bin/mc extracted from that image.

It lives here rather than in circulation because the image is shared by three
repos and belongs to none of them in particular.

The image is a bare passthrough with no Palace configuration, so the consuming
repos keep their own differing MinIO setups and change only a FROM line. It is
pinned to an immutable release tag and publishes no `latest`, and only pushes to
main publish, so an unmerged branch cannot overwrite that tag.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dbernstein
dbernstein merged commit 3206517 into main Sep 24, 2026
1 check passed
@dbernstein
dbernstein deleted the chore/minio-mirror-image branch September 24, 2026 20:07
dbernstein added a commit to ThePalaceProject/circulation that referenced this pull request Sep 25, 2026
## Description

Switches `docker/Dockerfile.minio.ci` from `quay.io/minio/minio:latest`,
which no longer permits
anonymous pulls, to the Palace mirror:

```diff
-FROM quay.io/minio/minio:latest AS minio
+# MinIO withdrew anonymous public access to its own image from both Docker Hub and quay.io, so
+# this pulls from the Palace mirror of the upstream release instead. The mirror is an unmodified
+# MinIO build, published from the ci-scripts repo:
+# https://github.com/ThePalaceProject/ci-scripts/blob/main/images/minio/Dockerfile
+# The tag is pinned deliberately; the mirror publishes no `latest`.
+FROM ghcr.io/thepalaceproject/palace-ci-minio:RELEASE.2025-09-07T16-13-09Z AS minio
```

That is the whole change: one `FROM` line, plus a comment recording why
it points somewhere
unusual. The mirror is an unmodified MinIO build, so the credentials,
ports and command below the
`FROM` are untouched.

The mirror is published and public:
`ghcr.io/thepalaceproject/palace-ci-minio` is live at digest

`sha256:0e8998d7ba6f742bac3c6ad22f354979b987d5d31c0a95b9b0dcad9d73e32751`
with `linux/amd64` and
`linux/arm64`, and an anonymous (unauthenticated) manifest request
returns 200.

It is published from
[ci-scripts](https://github.com/ThePalaceProject/ci-scripts) rather than
from
here, because the image is shared by three repos and belongs to none of
them in particular.
Companion one-line changes: ThePalaceProject/library-registry#1066 and
ThePalaceProject/virtual-library-card#1016. The three are independent
and can merge in any order.

## Motivation and Context

[JIRA](https://ebce-lyrasis.atlassian.net/browse/PP-5244)

All tox-docker CI jobs currently fail on `main` while building the MinIO
test container:

```
docker.errors.BuildError: unauthorized: access to the requested resource is not authorized
```

MinIO has withdrawn anonymous public access to its server image from
Docker Hub (~13 Sept, worked
around in #3728 by moving to quay.io) and
now from quay.io as well.
Ten checks fail on `main`: Tests (Py 3.12 / 3.13 / 3.14), OpenSearch
2.19, OpenSearch 3.5, Unit
tests (amd64 / arm64), Integration test (amd64 / arm64) and the
Backwards compatibility test. Lint,
mypy, CodeQL, the Migration test and the Docker build are unaffected
because they do not use
tox-docker. Local `tox` fails identically, so developers cannot run the
suites either.

Pinning an older tag does not help — the whole upstream repository is
gated, not just `:latest` —
and neither does a local Docker cache, because `tox_docker` passes
`pull=True` on every build.

Full background, registry probes and the retirement plan are in
ThePalaceProject/ci-scripts#2.

## How Has This Been Tested?

**This PR's own CI is the acceptance test, and it passes.** All ten
checks listed above are green
against the published mirror, including the Backwards compatibility test
and both Integration and
Unit test jobs on amd64 and arm64.

Locally, `tox -e py312-docker -- -m minio` was run against the real
`ghcr.io/thepalaceproject/palace-ci-minio` reference with the image
first cleared from the local
Docker cache, so the pull genuinely came from GHCR:

```
py312-docker: docker> build .../docker/Dockerfile.minio.ci target 'minio'
py312-docker: docker> run '2827512c875a' (from 'minio-circ')
py312-docker: commands[0]> pytest -m minio --no-cov -q
14 passed in 16.48s
```

Before the mirror was published, the same chain was exercised by pushing
the image to a throwaway
`registry:2` on localhost and temporarily pointing this `FROM` line at
it — `tox_docker` passes
`pull=True` on every build, so a local-only tag is rejected and a real
registry is required either
way. That run also gave 14 passed.

## Checklist

- [x] I have updated the documentation accordingly.
- [x] All new and existing tests passed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
dbernstein added a commit to ThePalaceProject/library-registry that referenced this pull request Sep 25, 2026
## Description

Switches the CI MinIO container from `quay.io/minio/minio:latest`, which
no longer permits
anonymous pulls, to the Palace mirror:

```diff
-FROM quay.io/minio/minio:latest AS minio
+# MinIO withdrew anonymous public access to its own image from both Docker Hub and quay.io, so
+# this pulls from the Palace mirror of the upstream release instead. The mirror is an unmodified
+# MinIO build, published from the ci-scripts repo:
+# https://github.com/ThePalaceProject/ci-scripts/blob/main/images/minio/Dockerfile
+# The tag is pinned deliberately; the mirror publishes no `latest`.
+FROM ghcr.io/thepalaceproject/palace-ci-minio:RELEASE.2025-09-07T16-13-09Z AS minio
```

That is the whole change to `docker/Dockerfile.minio.ci`: one `FROM`
line, plus a comment recording
why it points somewhere unusual. The mirror is an unmodified MinIO build
with no Palace
configuration baked in, so this repo keeps its own credentials, buckets
and entrypoint exactly as
they are.

The mirror is published and public:
`ghcr.io/thepalaceproject/palace-ci-minio` is live at digest

`sha256:0e8998d7ba6f742bac3c6ad22f354979b987d5d31c0a95b9b0dcad9d73e32751`
with `linux/amd64` and
`linux/arm64`, and an anonymous (unauthenticated) manifest request
returns 200.

## Motivation and Context

MinIO has progressively withdrawn public distribution of its server
image — from Docker Hub around
13 Sept, and from quay.io around 24 Sept. Both registries now answer 401
to anonymous manifest
requests for **every** tag, and `dl.min.io` answers 410. Any Dockerfile
doing
`FROM <registry>/minio/minio` therefore fails before the test suite
runs:

```
docker.errors.BuildError: unauthorized: access to the requested resource is not authorized
```

This repo moved to quay.io in PP-5132 when Docker Hub closed; quay.io
has now closed too, so that
workaround no longer helps. Two things that look like fixes are not:
pinning a digest or an older
tag does not help, because the whole upstream repository is gated rather
than a single tag; and a
local Docker cache does not help, because `tox_docker` passes
`pull=True` on every build, forcing a
fresh pull.

Because MinIO appears to be withdrawing public distribution
progressively, any third-party MinIO
source is likely to fail again, so the image is mirrored into the org's
own registry as
`ghcr.io/thepalaceproject/palace-ci-minio`, published from the
[ci-scripts](https://github.com/ThePalaceProject/ci-scripts) repo. It is
assembled from MinIO's
official GitHub release binaries — the one channel still served
anonymously — each pinned by
sha256, and those binaries are byte-for-byte identical to the ones
inside the last upstream image
CI used. It is public (no `docker login` for developers, no
package-access grants for CI) and
pinned to an immutable tag with no `latest`.

The mirror is a bridge, not a destination;
[PP-5245](https://ebce-lyrasis.atlassian.net/browse/PP-5245)
tracks replacing MinIO outright.
Full background, registry probes and the retirement plan are in
ThePalaceProject/ci-scripts#2.

## How Has This Been Tested?

**This PR's own CI is the acceptance test, and it passes** against the
published mirror.

Locally, the container built from this repo's
`docker/Dockerfile.minio.ci` came up healthy
(`/minio/health/live` returned 200) and `mc` inside the container
created a bucket successfully —
confirming the mirror carries the `mc` client and the `curl` that this
repo's setup and its
`docker-compose.yml` healthcheck rely on.

This file is byte-for-byte identical to circulation's
`docker/Dockerfile.minio.ci` (verified with
`diff`), and the same mirror was exercised end-to-end through `tox`
there: all 14 `minio`-marked
tests passed against a container built from it, pulling from GHCR with
the image cleared from the
local Docker cache.

## Checklist

- [x] I have updated the documentation accordingly.
- [x] All new and existing tests passed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


[PP-5245]:
https://ebce-lyrasis.atlassian.net/browse/PP-5245?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
dbernstein added a commit to ThePalaceProject/virtual-library-card that referenced this pull request Sep 25, 2026
## Description

Switches the CI MinIO container from `quay.io/minio/minio:latest`, which
no longer permits
anonymous pulls, to the Palace mirror:

```diff
-FROM quay.io/minio/minio:latest
+# MinIO withdrew anonymous public access to its own image from both Docker Hub and quay.io, so
+# this pulls from the Palace mirror of the upstream release instead. The mirror is an unmodified
+# MinIO build, published from the ci-scripts repo:
+# https://github.com/ThePalaceProject/ci-scripts/blob/main/images/minio/Dockerfile
+# The tag is pinned deliberately; the mirror publishes no `latest`.
+FROM ghcr.io/thepalaceproject/palace-ci-minio:RELEASE.2025-09-07T16-13-09Z
```

That is the whole change to `ci/minio/Dockerfile`: one `FROM` line, plus
a comment recording why it
points somewhere unusual. The mirror is an unmodified MinIO build with
no Palace configuration baked
in, so this repo keeps its own credentials, its `vlc-test` bucket and
its `entrypoint.sh` exactly as
they are.

**The README needed fixing too.** Step 3 of the local setup ("Set up
public MinIO bucket") told
developers to `docker run quay.io/minio/minio`, which now 401s just as
CI did — so a new developer
could not get VLC running locally. That command needed more than a
registry swap: the upstream image
wrapped the binary in an entrypoint script, so `... quay.io/minio/minio
server /data` worked, whereas
the mirror ships no entrypoint and the same arguments fail with
`exec: "server": executable file not found in $PATH`, leaving the
container in `Created` and never
running. The documented command now names the `minio` binary explicitly
and says why.

The mirror is published and public:
`ghcr.io/thepalaceproject/palace-ci-minio` is live at digest

`sha256:0e8998d7ba6f742bac3c6ad22f354979b987d5d31c0a95b9b0dcad9d73e32751`
with `linux/amd64` and
`linux/arm64`, and an anonymous (unauthenticated) manifest request
returns 200.

## Motivation and Context

MinIO has progressively withdrawn public distribution of its server
image — from Docker Hub around
13 Sept, and from quay.io around 24 Sept. Both registries now answer 401
to anonymous manifest
requests for **every** tag, and `dl.min.io` answers 410. Any Dockerfile
doing
`FROM <registry>/minio/minio` therefore fails before the test suite
runs:

```
docker.errors.BuildError: unauthorized: access to the requested resource is not authorized
```

This repo moved to quay.io in PP-5132 when Docker Hub closed; quay.io
has now closed too, so that
workaround no longer helps. Two things that look like fixes are not:
pinning a digest or an older
tag does not help, because the whole upstream repository is gated rather
than a single tag; and a
local Docker cache does not help, because `tox_docker` passes
`pull=True` on every build, forcing a
fresh pull.

Because MinIO appears to be withdrawing public distribution
progressively, any third-party MinIO
source is likely to fail again, so the image is mirrored into the org's
own registry as
`ghcr.io/thepalaceproject/palace-ci-minio`, published from the
[ci-scripts](https://github.com/ThePalaceProject/ci-scripts) repo. It is
assembled from MinIO's
official GitHub release binaries — the one channel still served
anonymously — each pinned by
sha256, and those binaries are byte-for-byte identical to the ones
inside the last upstream image
CI used. It is public (no `docker login` for developers, no
package-access grants for CI) and
pinned to an immutable tag with no `latest`.

The mirror is a bridge, not a destination;
[PP-5245](https://ebce-lyrasis.atlassian.net/browse/PP-5245)
tracks replacing MinIO outright.
Full background, registry probes and the retirement plan are in
ThePalaceProject/ci-scripts#2.

## How Has This Been Tested?

**This PR's own CI is the acceptance test, and it passes** against the
published mirror.

This repo asks more of the image than the other two do — its
`entrypoint.sh` needs a shell, `curl`
for the readiness loop, and the `mc` client — so the image was also
built from `ci/minio/Dockerfile`
and run locally against the mirror. The entrypoint ran to completion:

```
Waiting for MinIO to start...
MinIO is ready
Creating bucket: vlc-test
Bucket created successfully `vlcminio/vlc-test`.
Setting bucket policy to download (public read)
Access permission for `vlcminio/vlc-test` is set to `download`
MinIO setup complete
```

`/minio/health/live` returned 200, and an anonymous read of `vlc-test`
returned 200, confirming the
download policy took effect.

The README's instructions were then run verbatim against the published
mirror — the corrected
`docker run`, `docker exec -it minio bash`, `mc alias set`, `mc mb` and
`mc anonymous set public`.
All succeeded; the console on :9001 returned 200 and an anonymous read
of the bucket returned 200.
The pre-correction command was also run, to confirm it genuinely fails
rather than merely looking
wrong:

```
exec: "server": executable file not found in $PATH
```

## Checklist

- [x] I have updated the documentation accordingly.
- [x] All new and existing tests passed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


[PP-5245]:
https://ebce-lyrasis.atlassian.net/browse/PP-5245?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
dbernstein added a commit that referenced this pull request Sep 25, 2026
## Description

Names PP-5245 as the retirement ticket for the MinIO mirror, in the
three places that previously
said it should be retired without saying where to find the ticket:

- `images/minio/Dockerfile` — the "bridge, not a destination" note
- `.github/workflows/build-minio-mirror.yml` — the header
- `README.md` — a new `### Retirement` section

Two smaller cleanups while in there:

- The README's retirement section now carries the 5,000-download
deletion threshold **next to** the
`gh api -X DELETE` command, so the cost of waiting is visible right
where someone would go to act.
Previously the threshold was a trailing sentence and the command lived
only in a PR description.
- The workflow's "one-time manual step: flip the package to public" note
read as a pending TODO. It
has been done, so it now records what was done and notes it would need
doing again if the package
were ever recreated — GHCR creates packages private and the workflow
cannot change that.

## Motivation and Context

The mirror exists because MinIO withdrew anonymous public access to its
server image from both
Docker Hub and quay.io (#2). It is
deliberately a stopgap, and
`images/minio/Dockerfile` tells readers "do not add features to it" —
but it then pointed at a
"retirement ticket" that had no identifier, so there was no way to
follow the instruction to its
conclusion.

That gap matters more than a missing cross-reference normally would.
Retiring this gets strictly
harder with time: GitHub does not allow self-service deletion of a
public package once any version
passes 5,000 downloads, after which it takes a Support request. With
`pull=True` on every
tox-docker build, ephemeral CI runners and three repos pulling, an
untracked mirror is one that
quietly becomes permanent.

## Also: the mirror's entrypoint difference from upstream

A second commit records a behavioural difference that had already caused
a real breakage. The
upstream image set `ENTRYPOINT` to a `docker-entrypoint.sh` that
supplied the `minio` binary, so
`docker run <image> server /data` worked. This mirror ships no
entrypoint, so that same invocation
fails with `exec: "server": executable file not found in $PATH` and the
container never leaves
`Created`.

The three CI Dockerfiles all set their own command, so none of them hit
this — which is why it went
unnoticed. But virtual-library-card's README documented exactly that
invocation for local
development, and it broke silently (fixed in
ThePalaceProject/virtual-library-card#1016). The
Dockerfile now says so next to its `CMD`, so the next person invoking
the image directly finds it
before debugging a container that refuses to start.

## How Has This Been Tested?

The Dockerfile change is comment-only — no instruction changes — so the
image contents are
unchanged: the same release binaries pinned by sha256 and the same UBI
base pinned by digest.

Note that merging this **does** re-trigger the publish workflow, because
both changed files are in
its `paths:` filter. That is expected and harmless; the workflow's PR
run on this branch builds both
architectures and verifies every pinned checksum without pushing, which
is the check that the
Dockerfile is still valid. The published manifest digest may change even
though the contents do not,
since buildx attaches fresh provenance to each build — consumers pin the
tag, not the digest, so
nothing downstream is affected.

The entrypoint behaviour documented in the second commit was verified
against the published image:
`docker run <mirror> server /data --console-address ":9001"` fails as
described and leaves the
container in `Created`, while `docker run <mirror> minio server /data
--console-address ":9001"`
comes up healthy in ~2s, with `mc` and the console both working inside
it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants