Container registry
Container registry (push/pull close-the-loop)
Section titled “Container registry (push/pull close-the-loop)”The registry is the part most likely to trip operators up, because the push path (a developer’s machine) and the pull path (the Rise host’s Docker daemon) can use different URLs for the same registry.
The oci-client-auth registry provider can either carry static credentials or
rely on an existing docker login. The config carries two URLs:
| Config key | Used by | Reference value |
|---|---|---|
client_registry_url | rise deploy on a developer host (push) | registry.${RISE_DOMAIN} |
registry_url | the Rise host’s Docker daemon (pull) | rise-registry:5000 |
Both URLs point at the same registry content — only the network path differs.
1. Expose the registry (operator, once)
Section titled “1. Expose the registry (operator, once)”The base Compose file exposes the registry via Traefik at
registry.${RISE_DOMAIN} with TLS (le) and a basicauth middleware. Generate an
htpasswd entry and pass it as REGISTRY_BASIC_AUTH (escape $ as $$ in a
.env file):
htpasswd -nbB ci 's3cret'# ci:$2y$05$.... → REGISTRY_BASIC_AUTH='ci:$2y$05$....' (or $$ in .env)export RISE_REGISTRY_USERNAME=ciexport RISE_REGISTRY_PASSWORD=s3cretAn internet-exposed registry must have auth — hence the basicauth
middleware. REGISTRY_BASIC_AUTH configures Traefik with the password hash;
the optional plaintext RISE_REGISTRY_USERNAME / RISE_REGISTRY_PASSWORD pair
lets Rise send the matching login to authorized users. Anyone allowed to deploy
can retrieve this pair, so only configure it when all Rise users are trusted.
The internal pull path can stay unauthenticated within the trusted host network.
2. Push (developer host, possibly remote)
Section titled “2. Push (developer host, possibly remote)”With RISE_REGISTRY_USERNAME and RISE_REGISTRY_PASSWORD configured, deploy
directly; Rise returns the static pair from its authenticated, deployment-scoped
credentials endpoint and the CLI runs docker login automatically.
rise deploy --project myapp --image ... # builds + pushes to client_registry_urlIf the static pair is omitted, log in with the basicauth credentials first; the provider returns empty credentials and the CLI keeps using the stored login:
docker login registry.${RISE_DOMAIN}rise deploy --project myapp --image ...The push targets client_registry_url (registry.${RISE_DOMAIN}).
3. Pull (Rise host’s Docker daemon)
Section titled “3. Pull (Rise host’s Docker daemon)”The Rise backend mounts the host Docker socket, so every image pull is
executed by the host’s Docker daemon — not from inside the Compose network.
That daemon resolves registry_url’s host with the host’s resolver, which
does not consult Docker’s embedded DNS on rise_default. The default
registry_url=rise-registry:5000 therefore does not work out of the box on a
production host: rise-registry is only resolvable inside the Compose network,
and :5000 is plain HTTP, which the daemon rejects unless told otherwise. Pick
one of:
-
Internal path (default
registry_url=rise-registry:5000). Two host-daemon prerequisites:- Make
rise-registryresolvable by the host daemon — add a host entry (e.g.127.0.0.1 rise-registryin/etc/hosts, or anextra_hosts/ published-port mapping) so it reaches the registry container, and - Mark it insecure (plain HTTP): add
"rise-registry:5000"to the daemon’sinsecure-registriesin/etc/docker/daemon.jsonand restart Docker.
No auth is needed on this path — it never crosses the authenticated Traefik edge.
- Make
-
Host-published loopback. Publish the registry on a host loopback port (as the local overlay does,
127.0.0.1:5000:5000) and setRISE_REGISTRY_URL=127.0.0.1:5000. Still requires the matchinginsecure-registriesentry for127.0.0.1:5000. -
Public path. Point
RISE_REGISTRY_URLat the publicregistry.${RISE_DOMAIN}(TLS, no insecure-registry needed). The daemon then needs credentials too: rundocker login registry.${RISE_DOMAIN}on the Rise host, or add a matching entry to the daemon’s~/.docker/config.json.
Because all three URLs reference the same registry content, an image pushed to
registry.${RISE_DOMAIN} is the exact image the daemon pulls.