## TL;DR
The denied message means the push reached the registry with no credentials, the wrong credentials, or credentials that lack write rights on that repository. Re-authenticate to the exact registry host in the image tag and confirm the token scope, because registries intentionally give no further detail.

```text
denied: requested access to the resource is denied
```

## Steps

1. Confirm which registry host the image is actually tagged for:
```bash
docker image inspect [IMAGE]:[TAG] --format '{{.RepoTags}}'
```
Expected: a tag list showing the full host path, for example `registry.example.com/[TEAM]/[APP]:[TAG]`. You must log in to exactly this host.

2. Log in to that host using stdin so the credential never lands in shell history:
```bash
echo "[YOUR PASSWORD OR TOKEN VALUE]" | docker login [REGISTRY_HOST] -u [USERNAME] --password-stdin
```
Expected: `Login Succeeded`.

3. Rule out a stale credential entry by logging out and back in:
```bash
docker logout [REGISTRY_HOST]
docker login [REGISTRY_HOST] -u [USERNAME] --password-stdin
```
Expected: a fresh `Login Succeeded`, proving you are not running on a cached entry from a previous rotation.

4. In CI, verify the credential helper actually has an entry for the host:
```bash
echo "[REGISTRY_HOST]" | docker-credential-[HELPER] get
```
Expected: output naming the ServerURL, Username, and a Secret value for the host. If it returns nothing, the helper has no entry and the push went anonymous.

5. Push and watch for whether the denial repeats with fresh credentials:
```bash
docker push [REGISTRY_HOST]/[TEAM]/[APP]:[TAG]
```
Expected: layers upload and a final digest line. If it still denies, the credential is valid but lacks push scope on that repo, so fix the access grant in the registry, not the client.

## When to use
- `docker push` fails with the denied message as soon as the push starts
- A CI job that used to push fine started denying after a credential rotation
- You can pull from the registry but cannot push to it

## When not to use
- The failure says `unauthorized: authentication required` before any push attempt, which is a missing login rather than a denied write
- The push fails with `name unknown` or a 404, which means the repository name itself is wrong
- The daemon reports DNS or TLS errors, meaning the push never reached the registry

## Why it happens
Docker sends whatever credential is stored for the registry host in `~/.docker/config.json` or returned by the configured credential helper. A tag host that differs from the login host, a stale token after rotation, or a token scoped pull-only all produce the identical denial, and registries deliberately do not distinguish bad credentials from insufficient scope in this message.

## Edge cases
- You logged in to `docker.io` but tagged the image for a mirror or a registry host with a port; log in to the host as it appears in the tag
- Docker Desktop credential helpers keep an old token after `docker login`; run `docker logout` for the host first, then log in again
- Org registries deny when the token was issued for a different org than the repo belongs to
- Tokens minted through an SSO flow can expire independently of the CLI session, so a morning push can fail where yesterday's worked

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_ELqUImi6-mURwcQfTq_Bzw
