feat: serve local docker repos as a real registry #103

Merged
benvin merged 1 commits from benvin/local-docker-registry into master 2026-07-05 16:55:54 +10:00
Owner

Why

Local docker repos had no write path — the /v2 Docker Registry API only proxied to upstreams. This makes a local docker repo a genuine container registry so docker push/docker pull (and podman/skopeo/buildah) work against it directly, matching the project principle that a local repo is the real thing rather than a mirror.

Changes

  • Implement the Docker Registry HTTP API V2 read/write half for local docker repos: blob uploads (monolithic and chunked POST/PATCH/PUT), manifest push, tags/list, and blob/manifest GET/HEAD.
  • Store blobs and manifests through the existing content-addressable store; keep a local_files reference per (repo, image) so the GC does not reap them. Tags are mutable (UpsertLocalFile); digests and blobs are immutable.
  • Dispatch /v2 reads to the local handler for local docker repos and fall through to the upstream proxy otherwise; writes are local-docker only.
  • Add UpsertLocalFile for mutable tag references.
  • Cover the push/pull round-trip with a dockerised e2e test and unit-test the registry path parser. Document the registry in the README.

Verification

  • scripts/docker-e2e.sh passes, including the new TestLocalDockerPushPull.
  • Verified a real end-to-end round-trip with skopeo against a live instance: pushed hello-world, pulled it back, loaded it into the docker daemon, and ran it successfully.
## Why Local `docker` repos had no write path — the `/v2` Docker Registry API only proxied to upstreams. This makes a local docker repo a genuine container registry so `docker push`/`docker pull` (and podman/skopeo/buildah) work against it directly, matching the project principle that a local repo is *the real thing* rather than a mirror. ## Changes - Implement the Docker Registry HTTP API V2 read/write half for local docker repos: blob uploads (monolithic and chunked POST/PATCH/PUT), manifest push, `tags/list`, and blob/manifest GET/HEAD. - Store blobs and manifests through the existing content-addressable store; keep a `local_files` reference per (repo, image) so the GC does not reap them. Tags are mutable (`UpsertLocalFile`); digests and blobs are immutable. - Dispatch `/v2` reads to the local handler for local docker repos and fall through to the upstream proxy otherwise; writes are local-docker only. - Add `UpsertLocalFile` for mutable tag references. - Cover the push/pull round-trip with a dockerised e2e test and unit-test the registry path parser. Document the registry in the README. ## Verification - `scripts/docker-e2e.sh` passes, including the new `TestLocalDockerPushPull`. - Verified a real end-to-end round-trip with skopeo against a live instance: pushed `hello-world`, pulled it back, loaded it into the docker daemon, and ran it successfully.
unkinben added 1 commit 2026-07-04 22:34:09 +10:00
feat: serve local docker repos as a real registry
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
26b405a948
Local docker repos previously had no write path — the /v2 Docker Registry
API only proxied to upstreams. This makes a local docker repo a genuine
registry so `docker push`/`docker pull` (and podman/skopeo/buildah) work
against it directly, matching the project principle that a local repo is the
real thing rather than a mirror.

- Implement the Docker Registry HTTP API V2 write/read half for local docker
  repos: blob uploads (monolithic and chunked POST/PATCH/PUT), manifest push,
  tags list, and blob/manifest GET/HEAD.
- Store blobs and manifests through the existing content-addressable store;
  keep a local_files reference per (repo, image) so the GC does not reap them.
  Tags are mutable (UpsertLocalFile); digests and blobs are immutable.
- Dispatch /v2 reads to the local handler for local docker repos and fall
  through to the upstream proxy otherwise; writes are local-docker only.
- Add UpsertLocalFile for mutable tag references.
- Cover the push/pull round-trip with a dockerised e2e test and unit-test the
  registry path parser. Document the registry in the README.
benvin merged commit a92ede23f6 into master 2026-07-05 16:55:54 +10:00
benvin deleted branch benvin/local-docker-registry 2026-07-05 16:55:55 +10:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unkin/artifactapi#103