DEV Community

Wen Ping
Wen Ping

Posted on

Start a free cloud Docker registry: push, pull, and public browse

docker push returns denied, and you do not want Harbor or a bare registry:2 plus certs and insecure-registries first. Start on an HTTPS cloud registry: create a Docker HOSTED in the console, docker login, then push as host/repo-name/image:tag. When partners only need anonymous pull, mark a delivery repo public and copy the install command from /explore.

Takeaway: Cloud can host Docker/OCI; docker push only into HOSTED; PROXY/GROUP are read-only; never hand-write /v2 into the image name; public distribution uses a separate public HOSTED plus host path /explore. Auth = repository ACL + tokens—no out-of-the-box tenant_id. Hub rate limits and rewriting FROM are in: Docker Hub pull limits.

Full self-host install and insecure-registries belong in: how to use a private Docker registry. Below fills in cloud HTTPS getting started, second-machine acceptance, and /explore.

1. Cloud vs Community self-host

Path Notes
Cloud Managed HTTPS; sample host https://repo.anguskit.com—usually no insecure-registries. Trust the console connection config for your tenant host
Community self-host GPL-3.0; fit for intranet and offline—you own machines, certs, and networking

Usage and limits follow the current tenant in the console; push is rejected at the ceiling. Delete old tags from the HOSTED artifact / tag list in the console (labels vary by UI). Prefer small base images and fewer historical tags for large layers.

2. Minimal topology

Example name Type Role
docker-hosted HOSTED Only push target
dockerhub-proxy PROXY Cache Docker Hub (remote https://registry-1.docker.io; configure a Hub account)
docker-group (optional) GROUP Unified pull entry over hosted + proxy

Whole-registry Harbor migration with digest dual-run: Harbor migration checklist. Many runners hitting Hub quotas and rewriting FROM: Docker Hub pull limits—this article does not expand Hub credential detail.

docker push  ──► docker-hosted (HOSTED, only write path)
docker pull  ──► HOSTED or docker-group ──► hosted + dockerhub-proxy
Partner anon ──► /explore ──► public-docker (separate public HOSTED)
Cloud HTTPS  ──► usually no insecure-registries
Enter fullscreen mode Exit fullscreen mode

3. Hands-on steps

3.1 Repos and tokens

  1. Create a Docker HOSTED (and optional PROXY/GROUP) in the console.
  2. Issue a Deploy Token (repod_) or user access token (PAT): push identity needs Write on HOSTED; pull identity needs Read on the entry repo.
  3. Password field = token; username = console username (trust connection config).

3.2 Login username trap (Docker ≠ PyPI)

Pattern Result
Username = console account, password = token Correct
Username __token__, password = token Wrong—that sentinel is for PyPI / some format manuals; do not use it with docker login
Username = token, empty password Fails; the two sides are reversed
Username = email alias that is not the console account Use the username shown in connection config

3.3 Login, tag, push

export REPO_HOST="repo.anguskit.com"
export REPO_USER="your_console_username"
export REPO_TOKEN="your_token"

echo "$REPO_TOKEN" | docker login "$REPO_HOST" \
  --username "$REPO_USER" \
  --password-stdin

docker tag myapp:1.0.0 \
  "${REPO_HOST}/docker-hosted/myapp:1.0.0"

docker push "${REPO_HOST}/docker-hosted/myapp:1.0.0"
Enter fullscreen mode Exit fullscreen mode

Image coordinates are host/repo-name/image:tag. Protocol /v2 must not appear in the image name. Prefer --password-stdin so the token stays out of shell history.

3.4 Acceptance (this machine + a second machine / clean CI)

On the push machine:

# Pull back from HOSTED
docker pull "${REPO_HOST}/docker-hosted/myapp:1.0.0"

# Record digest for cross-machine checks
docker image inspect "${REPO_HOST}/docker-hosted/myapp:1.0.0" \
  --format '{{index .RepoDigests 0}}'
Enter fullscreen mode Exit fullscreen mode

On a second machine or clean CI job (no leftover local tags):

# Pull only—do not trust layers left from a local build
echo "$REPO_TOKEN" | docker login "$REPO_HOST" \
  --username "$REPO_USER" --password-stdin

docker pull "${REPO_HOST}/docker-hosted/myapp:1.0.0"

docker image inspect "${REPO_HOST}/docker-hosted/myapp:1.0.0" \
  --format '{{index .RepoDigests 0}}'
Enter fullscreen mode Exit fullscreen mode

Matching digests on both machines means host acceptance passed. With a GROUP configured, read-only pulls can use the GROUP name as entry (still cannot push into GROUP):

# docker pull "${REPO_HOST}/docker-group/myapp:1.0.0"
Enter fullscreen mode Exit fullscreen mode

When pulling Hub official images via PROXY/GROUP, add library/ (for example …/library/nginx:1.27). Detail: Docker format manual.

4. /explore public discovery (hands-on)

When partners will not hold a token:

  1. Create a separate public-docker HOSTED and mark it public (isPublic). Do not publicize day-to-day docker-hosted, and do not publicize a GROUP that aggregates private repos.
  2. Use a Write token to push release tags only to public-docker (keep dev-tmp and date-stamped tags out of the public list).
  3. Open https://repo.anguskit.com/explore in a private window (or search on /explore/artifacts).
  4. Open the artifact detail page and copy the credential-free docker pull command.
  5. Run it in a clean environment that has not docker login’d your team private repos; it should pull without a token.

Index lag after flipping public may be tens of seconds to a few minutes. While portal top-bar “Docs” stays disabled, point outsiders at the AngusKit docs site. Full portal rules: publish private artifacts for public download.

5. Boundaries and failure table

Symptom Likely cause Fix
denied Not logged in, no Write, pushed to GROUP Confirm HOSTED name and token ACL
Name contains /v2 Protocol path in the image name Drop /v2; match connection config
Storage full / push rejected Usage ceiling (current tenant) Delete old tags; or Community self-host
Partner still 401 Repo not public or wrong private link Use the /explore-generated command
Hub official image pull fails PROXY missing or no library/ Check PROXY; rate-limit cases → rate-limit article
unauthorized Password is not the token, or username wrong See §3.2; username ≠ __token__
Second machine digest mismatch Wrong tag / stale cache Pull explicit :tag or by digest

The same repos can also host Maven/npm and other formats; multi-format co-location: selection article.

FAQ

Do I still need insecure-registries on cloud?

Usually not when repo.anguskit.com is HTTPS. HTTP self-host does—see: how to use a private Docker registry.

Can this replace Docker Hub?

For your own business images and public images cached via PROXY, it can replace “every machine hits Hub directly.” Hub accounts, official star pages, and similar are out of scope—see: Docker Hub pull limits.

Is admission gate on by default?

No. Repo enforces; Security runs deep engines; a successful upload does not mean a scan already ran.

Can cloud images run in production?

Push and pull work technically. Whether it is enough depends on the current tenant’s usage and limits; otherwise Community self-host (you own certs / networking).

Takeaways

  • Cloud can run the main private-image path (HOSTED / PROXY / GROUP).
  • push → HOSTED; pull → HOSTED or GROUP; accept with digests on a second machine.
  • External: public-docker + /explore; no /v2 in image names; login username is not __token__.

Reference articles

Top comments (0)