Container registry authentication
repo2rlenv push (v0.8.2.post3+) uploads the bootstrap Docker image to an
OCI registry alongside the HF Hub dataset so any consumer can harbor run
the published tasks. This page covers how to log into each supported
registry and verify the credentials work.
Run repo2rlenv push --check-auth to probe every detected registry and
get a one-shot report. It pushes no image and leaves nothing behind.
Default flow
You don't have to pre-configure anything. repo2rlenv push auto-detects
the first verified registry from ~/.docker/config.json. If nothing is
logged in, push falls back to inline-Dockerfile mode (recipe-level
reproducibility) and tells you how to upgrade.
For launches and CI, use --require-registry to hard-fail instead of
falling back silently.
GHCR (default recommendation)
Free for public images, no anonymous-pull rate limit, and it maps naturally onto a GitHub org. Recommended default for new datasets.
gh auth refresh -h github.com -s write:packages
echo "$(gh auth token)" | docker login ghcr.io \
-u "$(gh api user --jq .login)" --password-stdinrepo2rlenv push will pick ghcr.io/<hf-dataset-owner>/... automatically.
If you lack write:packages on that GitHub org, push falls back to
ghcr.io/<gh-login-user>/.... Repository visibility is flipped to public
via the GitHub API (PATCH /user|orgs/packages/container/<name>) when the
HF dataset is public.
AWS ECR Private
Token TTL is 12h, so install amazon-ecr-credential-helper once and
forget about it.
brew install docker-credential-helper-ecr # or apt
# Add to ~/.docker/config.json:
# "credHelpers": { "<acct>.dkr.ecr.<region>.amazonaws.com": "ecr-login" }Or one-off (re-run every 12h):
aws ecr get-login-password --region us-east-1 \
| docker login --username AWS --password-stdin \
<acct>.dkr.ecr.us-east-1.amazonaws.comECR requires the repository to pre-exist; repo2rlenv push creates it
automatically via aws ecr create-repository if the L4 probe returns 404.
Make sure your IAM role has ecr:CreateRepository.
AWS ECR Public
A separate service from ECR Private. 50 GB free public storage, forever.
aws ecr-public get-login-password --region us-east-1 \
| docker login --username AWS --password-stdin public.ecr.awsOr use amazon-ecr-credential-helper against public.ecr.aws.
Azure Container Registry
Token TTL is 3h.
az login # one-time
az acr login --name <myregistry> # per sessionFor anonymous public pulls (Standard tier or higher):
az acr update -n <reg> --anonymous-pull-enabled true.
GCP Artifact Registry
gcloud registers itself as a Docker credential helper per region:
gcloud auth login
gcloud auth configure-docker us-central1-docker.pkg.devRepository must pre-exist; repo2rlenv push creates it via
gcloud artifacts repositories create if the L4 probe returns 404.
For public pulls:
gcloud artifacts repositories add-iam-policy-binding <repo> \
--location=us-central1 --member=allUsers \
--role=roles/artifactregistry.readerDocker Hub
The default tier has a 100 pulls / 6h / IP anonymous limit. That's
fine for small datasets, but a real problem for benchmarks pulled by many
consumers or in CI. repo2rlenv push will NOT pick Docker Hub as the
auto-default when other registries are available; pass --image-registry index.docker.io/<user> to force it.
docker login # interactive PAT prompt
# OR
echo "$DOCKER_TOKEN" | docker login -u "$DOCKER_USERNAME" --password-stdinCredential resolution. For Docker Hub the probe prefers the explicit
env vars DOCKER_USERNAME + DOCKER_TOKEN (a PAT) over the docker
credstore. The credstore returns an OAuth identity token that is often
pull-only at the token endpoint, while an explicit PAT reliably grants
push. The push namespace is the authenticated Docker Hub user
(DOCKER_USERNAME), not the HF dataset owner, so images land under
index.docker.io/<DOCKER_USERNAME>/…. (GHCR analogously reads
GHCR_TOKEN / GITHUB_TOKEN.)
Multi-repo datasets (e.g. pr_runtime across many repos, with one
bootstrap image per repo) are fully supported: push pushes each
distinct image and rewrites each task's environment/Dockerfile to
its own registry digest. If any push fails (or no registry is verified),
it falls back to inline mode: each task bakes its own rebuild recipe and
stays reproducible with no registry at all.
Local / registry:2 (testing only)
For development tests that need a real OCI registry but don't want any cloud signup:
docker run -d -p 5000:5000 --name r2e-test-reg registry:2
repo2rlenv push ./datasets/mydataset owner/repo \
--image-registry localhost:5000The probe correctly classifies localhost and skips L2 auth (the default registry:2 image runs without auth). For an authenticated local registry, see the upstream docs at https://distribution.github.io/distribution.
Anonymous-ephemeral: ttl.sh
For one-shot end-to-end smoke tests with no signup:
repo2rlenv push ./datasets/mydataset owner/repo \
--image-registry ttl.shImages auto-delete after 1h (configurable in the tag).
What --check-auth actually probes
For each registry the L1–L4 protocol runs in order:
| Level | Endpoint | What it confirms |
|---|---|---|
| L1 | GET /v2/ | Registry reachable |
| L2 | Bearer-token exchange | Credentials parse + registry accepts them |
| L3 | HEAD /v2/<ns>/r2e-bootstrap-probe/manifests/latest (404 = pass) | Read access on target namespace |
| L4 | POST /v2/<ns>/r2e-bootstrap-probe/blobs/uploads/ + DELETE cancel | Write access |
L4 leaves no image, layer, or session artifact. Total wire time per
registry: ~200–500 ms. --fast stops at L2 if you just want a quick
sanity check.