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 pushonly into HOSTED; PROXY/GROUP are read-only; never hand-write/v2into the image name; public distribution uses a separate public HOSTED plus host path/explore. Auth = repository ACL + tokens—no out-of-the-boxtenant_id. Hub rate limits and rewritingFROMare 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
3. Hands-on steps
3.1 Repos and tokens
- Create a Docker HOSTED (and optional PROXY/GROUP) in the console.
- Issue a Deploy Token (
repod_) or user access token (PAT): push identity needs Write on HOSTED; pull identity needs Read on the entry repo. - 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"
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}}'
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}}'
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"
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:
- Create a separate
public-dockerHOSTED and mark it public (isPublic). Do not publicize day-to-daydocker-hosted, and do not publicize a GROUP that aggregates private repos. - Use a Write token to push release tags only to
public-docker(keepdev-tmpand date-stamped tags out of the public list). - Open
https://repo.anguskit.com/explorein a private window (or search on/explore/artifacts). - Open the artifact detail page and copy the credential-free
docker pullcommand. - 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/v2in image names; login username is not__token__.
Reference articles
- How to use a private Docker registry (self-host): https://www.anguskit.com/en/blog/private-docker-registry
- Docker format manual: https://www.anguskit.com/en/docs/repo/manual/05-formats/02-docker
- Public portal manual: https://www.anguskit.com/en/docs/repo/manual/15-portal
- Publish private artifacts for public download: https://www.anguskit.com/en/blog/public-portal-launch
- Harbor image migration: https://www.anguskit.com/en/blog/harbor-to-angusrepo-image-migration
- Docker Hub pull limits: https://www.anguskit.com/en/blog/docker-hub-pull-limit-alternative
- Deploy Token and ACL: https://www.anguskit.com/en/blog/angusrepo-deploy-token-pat-acl-guide
- Selection: one registry instead of many: https://www.anguskit.com/en/blog/repo-selection-2026
Top comments (0)