Docker Registry Standards
The RepoForge.io Docker registry complies with the following Open Container Initiative (OCI) and Docker specifications, so docker, buildx, containerd, podman, skopeo, crane, oras and cosign work against it without extra configuration.
Registry API
| Standard | Specification |
|---|---|
| OCI Distribution Spec v1.1 | Distribution Specification |
| Docker Registry HTTP API V2 | HTTP API V2 |
| Docker Token Authentication | Token Authentication Specification |
| Docker Token Scopes | Token Scope Documentation |
Every response carries the Docker-Distribution-API-Version: registry/2.0 header, and errors use the spec's {"errors": [{"code": ..., "message": ..., "detail": ...}]} format with codes such as BLOB_UNKNOWN, MANIFEST_UNKNOWN, DIGEST_INVALID and UNAUTHORIZED.
Images
| Standard | Specification |
|---|---|
| OCI Image Manifest | Image Manifest Specification |
| OCI Image Index | Image Index Specification |
| OCI Content Descriptors | Descriptors and digests |
| Docker Image Manifest V2, Schema 2 | Image Manifest V2, Schema 2 |
This covers single-platform images, multi-platform images built with docker buildx, Docker manifest lists, and artifacts such as signatures, SBOMs and attestations that use subject, artifactType and annotations. Manifests are stored and served byte for byte as they were pushed, so the body always hashes to its Docker-Content-Digest. Blob digests can use sha256 or sha512; manifest digests use sha256.
Supported Endpoints
All paths are relative to https://docker.repoforge.io/v2/, where <name> is your hash ID followed by the registry name, for example repoforge-hash-id/name-of-registry. Registry names can contain / to group images, for example repoforge-hash-id/team/app.
| Endpoint | Purpose |
|---|---|
GET /v2/ | Check the registry is available and the token is valid |
GET /v2/_catalog | List the registries in your account |
GET /v2/<name>/tags/list | List tags, paged with n and last and a Link header |
HEAD, GET /v2/<name>/manifests/<reference> | Check or pull a manifest by tag or digest |
PUT /v2/<name>/manifests/<reference> | Push a manifest or image index |
DELETE /v2/<name>/manifests/<reference> | Delete a tag, or a manifest by digest |
HEAD, GET /v2/<name>/blobs/<digest> | Check or pull a blob, including byte ranges with Range |
DELETE /v2/<name>/blobs/<digest> | Delete a blob that no manifest references |
POST /v2/<name>/blobs/uploads/ | Start a chunked upload, upload a blob in one request with ?digest=, or mount a blob from another registry with ?mount=<digest>&from=<name> |
PATCH, PUT /v2/<name>/blobs/uploads/<uuid> | Upload a chunk, then complete the upload |
GET, DELETE /v2/<name>/blobs/uploads/<uuid> | Check the progress of an upload, or cancel it |
GET /v2/<name>/referrers/<digest> | List the signatures, SBOMs and attestations that refer to a manifest, optionally filtered by artifactType |
Push Checks
When you push an image, RepoForge.io also:
- hashes every uploaded blob and rejects the upload with
400 DIGEST_INVALIDif it doesn't match the digest your client sends - checks that a manifest pushed by digest hashes to that digest, and that its
Content-Typematches itsmediaType - rejects a manifest with
400 MANIFEST_BLOB_UNKNOWNif it references a blob or child manifest that hasn't been pushed - rejects a tag that isn't a valid tag name with
400 TAG_INVALID - rejects manifests larger than 256 KiB with
413 SIZE_INVALID
When a tag is moved to a new image, the old image is only removed once no other tag, image index or artifact refers to it, so layers shared between tags are never lost.
Tokens and Scopes
Clients request a token for the registries and actions they need, using scopes such as repository:repoforge-hash-id/name-of-registry:pull,push. RepoForge.io only grants the actions your user or access token is allowed:
| Action | Allows | Role |
|---|---|---|
pull | Pulling manifests, tags and blobs | Docker - Read only or Docker - Full access |
push | Uploading blobs and pushing manifests | Docker - Full access |
delete | Deleting tags, manifests and blobs | Docker - Full access |
If registry-level permissions are on, the registry's own roles are used instead. Anyone can get a pull token for a public registry without logging in, but never a push or delete token.
A request without a valid token, or with a token that doesn't cover it, returns 401 Unauthorized with a WWW-Authenticate header naming the scope it needs, so clients can fetch the right token and retry.
Delete an Image
docker can't delete images from a registry, but tools that use the registry API can. For example, with crane:
crane auth login docker.repoforge.io -u __token__ -p "$REPOFORGE_TOKEN"
crane delete docker.repoforge.io/repoforge-hash-id/name-of-registry:old-tagDeleting a tag removes only that tag. Deleting by digest, for example crane delete docker.repoforge.io/repoforge-hash-id/name-of-registry@sha256:..., removes the image and every tag pointing at it. Either way, layers are removed only once no other image uses them.