Skip to main content

The stack

Two containers, run with Docker Compose, plus a sprinkle of auth:

Registry-Server (10.100.100.6)
  registry        (registry:2)         :5000  - the registry API
  registry-ui     (joxit UI)           :8080  - a browser front-end
  auth: htpasswd  (user <REDACTED>)            - basic auth on pushes/pulls
  fronted by HAProxy: registry.example.com (API) + docker.example.com (UI)
  • The registry itself serves the Docker/OCI API on 5000. Basic auth (an htpasswd file) means you can't push or pull without credentials.
  • A web UI gives a human-friendly view of what's stored — handy for confirming a tag landed.
  • The edge publishes both: registry.example.com for the API and docker.example.com for the UI, with TLS as always handled by HAProxy.

A small but important detail: clients push to the public TLS name (registry.example.com), so Docker is happy about certificates, rather than to a plain-HTTP internal address (which would require fiddly "insecure registry" config on every client). One more payoff of terminating TLS at the edge.

Why we use this: a registry is "just" an HTTP API in front of a blob store — but auth, TLS, and a UI are what make it usable and safe. Assembling those from small pieces is more instructive than any managed registry.

Diagram

Push, pull, and a safe weekly garbage-collection sweep