Registries
drydock supports most registries:
drydock supports 23 registries:
- ACR (Azure Container Registry)
- ALICR (Alibaba Cloud Container Registry)
- Artifactory (JFrog Artifactory)
- Codeberg (Codeberg Container Registry)
- CUSTOM (Self-hosted Registry)
- DHI (Docker Hardened Images)
- DOCR (DigitalOcean Container Registry)
- ECR (Amazon Elastic Container Registry)
- FORGEJO (Forgejo Container Registry)
- GAR (Google Artifact Registry)
- GCR (Google Container Registry)
- GHCR (Github Container Registry)
- GITEA (Gitea Container Registry)
- GITLAB (Gitlab Container Registry)
- Harbor
- HUB (Docker Hub)
- IBMCR (IBM Cloud Container Registry)
- LSCR (LinuxServer Container Registry)
- MAU (dock.mau.dev Registry)
- Nexus (Sonatype Nexus)
- OCIR (Oracle Cloud Infrastructure Registry)
- Quay
- TrueForge (TrueForge OCI Registry)
Naming registry instances
Registry env vars use the pattern DD_REGISTRY_<TYPE>_<INSTANCE>_<KEY> — the <INSTANCE> part (shown as {REGISTRY_NAME} in tables on the pages below) is a label you pick. It lets you register multiple instances of the same registry type (e.g. one private GHCR account plus the public one). Existing examples use PUBLIC for Docker Hub and PRIVATE for GHCR:
- DD_REGISTRY_HUB_PUBLIC_LOGIN=myuser
- DD_REGISTRY_HUB_PUBLIC_PASSWORD=dckr_pat_xxx
- DD_REGISTRY_GHCR_PRIVATE_USERNAME=myuser
- DD_REGISTRY_GHCR_PRIVATE_TOKEN=ghp_xxxPick whatever label is meaningful for you — PRIVATE, WORK, MYCO all work. The label is internal-only; it never appears in image references.
Registry routing
When multiple instances of the same registry type are configured (one anonymous and one credentialed), drydock gives explicit priority to credentialed instances. The previous silent anonymous fallback on 401/403 is removed — an auth rejection now surfaces as an actionable "Check failed" badge in the UI instead of silently retrying as a public caller.
Credentialed instances take priority
If you configure both a credentialed and an anonymous instance of the same registry type, drydock will always route image lookups through the credentialed instance. To use anonymous access for specific images, register a separate anonymous instance with a distinct {INSTANCE} name and route those containers explicitly.
Rate limiting and retry
drydock applies a per-host token bucket to all outbound registry calls and automatically retries on 429 and 503 responses. Default rates:
| Host | Rate | Burst |
|---|---|---|
ghcr.io | 2 req/s | 5 |
registry-1.docker.io (Docker Hub) | 2 req/s | 5 |
api.github.com | 1 req/s | 3 |
| All other hosts | 5 req/s | 10 |
On a 429 or 503 response, drydock honors the upstream Retry-After header (both seconds and HTTP-date forms) and falls back to exponential backoff (1 s → 2 s → 4 s, capped at 60 s), up to 3 retries per call.
0 */6 * * * (every 6 hours). High-container-count deployments (40+ containers with many-page tag lists) benefit most from leaving the 6-hour default in place. See Watcher cron and rate limits for guidance.TLS and insecure registries
Registry instances configured with INSECURE=true (TLS certificate validation disabled) emit a warn-level log on every request as a reminder that certificate validation is off. This log fires for each outbound call, so it is visible in normal docker logs drydock output.
Use INSECURE=true only for self-hosted registries on private networks where a valid TLS certificate cannot be provisioned. For production registries reachable over the internet, always use a valid certificate.
Automatic Bearer token exchange
When a registry responds to a tag-list or manifest request with 401 Unauthorized and a WWW-Authenticate header containing a Bearer realm=…,service=…,scope=… challenge, drydock automatically performs the standard Docker Registry v2 token-auth flow: it fetches a token from the realm endpoint (anonymously for public images, or with the configured credentials for private ones) and retries the request once. The Bearer challenge can appear alongside other schemes such as Basic, and token responses may use either token or access_token.
This covers registries that do not require a pre-authenticated session, including:
- Public images on Codeberg (
codeberg.org) and other Forgejo/Gitea instances - Chainguard (
cgr.dev) and other registries that always challenge before serving tag lists
The realm authority is validated against the registry's own configured authority before any credentials are sent, including non-default ports. The exchange is silently skipped if the challenge points to an untrusted host or port, and the original 401 is returned instead. If credentials were configured and the trusted token endpoint rejects them with 401 or 403, drydock surfaces a credential-specific authentication error instead of falling back to the original registry 401. Providers that already perform proactive Bearer auth (GHCR, Docker Hub, Quay) are unaffected.
Registry lookup image (dd.registry.lookup.image)
The dd.registry.lookup.image container label redirects tag and manifest queries to an alternative image reference (e.g. check Docker Hub's library/nextcloud for a container running from a private mirror). In v1.5.0, this substitution is applied only at query boundaries (getTags, getImageManifestDigest, getImagePublishedAt) and no longer overwrites the container's deploy identity (image.name, image.registry.url). This means compose-file rewrites and container recreates always use the original image, not the lookup target.
Un-prefixed images (e.g. nginx:1.0) now default to docker.io for the registry URL.