Skip to content

GitHub Actions job fails pulling minio/minio image with access denied, repository does not exist or may require 'docker login'

GitHub Actions job running docker compose up -d --wait db minio started failing at the pull step with minio Error pull access denied for minio/minio, repository does not exist or may require 'docker login': denied: requested access to the resource is denied. The compose file pins minio/minio:RELEASE.2025-02-18T16-25-55Z and minio/mc:RELEASE.2025-02-15T10-36-16Z, and the same compose stack starts fine on the developer's laptop, so the pin looked correct. Switching to quay.io/minio/minio:<same tag> (what MinIO's own docs used to recommend, and what another repo's CI pulled successfully a few days earlier) also fails: docker pull reports unexpected status from HEAD request to https://quay.io/v2/minio/minio/manifests/RELEASE.2025-02-18T16-25-55Z: 401 UNAUTHORIZED, and docker manifest inspect on Docker Hub says unauthorized: authentication required. Local docker compose up keeps working because the image is already in the local cache, which hides the breakage until a fresh clone or CI runner tries to pull.

1 solution
ranked by outcome — not votes
Accepted

Upstream MinIO community images are no longer anonymously pullable from either registry: minio/minio and minio/mc on Docker Hub return pull access denied, and quay.io/minio/minio / quay.io/minio/mc return 401 on the manifest HEAD (observed September 2026; quay pulls from GitHub-hosted runners still worked about two days earlier). Every existing tag is affected, not just latest. Machines that already cached the image keep working, so only fresh clones and CI break.

Fix: switch to the community-maintained fork published by Pigsty on Docker Hub, which is a drop-in replacement:

minio:
  image: pgsty/minio:RELEASE.2026-08-04T00-00-00Z   # was minio/minio:RELEASE.2025-02-18T16-25-55Z
  command: server /data --console-address ":9001"
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
minio-init:
  image: pgsty/mc:RELEASE.2026-09-16T00-00-00Z       # was minio/mc:RELEASE.2025-02-15T10-36-16Z
  entrypoint: ["/bin/sh", "-c", "mc alias set local http://minio:9000 minioadmin minioadmin && mc mb -p local/my-bucket"]

Why it is drop-in:

  • Same entrypoint (/usr/bin/docker-entrypoint.sh, cmd minio), so server /data ... commands are unchanged.
  • curl is bundled, so the standard /minio/health/live healthcheck and docker compose up --wait still work.
  • pgsty/mc has /bin/sh, so sh -c "mc alias set ... && mc mb ..." bucket-init one-shots still work.
  • Multi-arch (amd64 + arm64 tags).
  • Data format is compatible: an object written by minio/minio:RELEASE.2025-02-18T16-25-55Z to a named volume was read back unchanged by pgsty/minio:RELEASE.2026-08-04T00-00-00Z on the same volume, so existing dev volumes carry over.

Check whether a pin is still pullable without relying on the local cache: docker manifest inspect <image:tag> (it queries the registry, not the cache).