Skip to content

Fix/docker provider registry reference - #5470

Open
Rackme wants to merge 3 commits into
Dokploy:canaryfrom
Rackme:fix/docker-provider-registry-reference
Open

Rackme wants to merge 3 commits into
Dokploy:canaryfrom
Rackme:fix/docker-provider-registry-reference

Conversation

@Rackme

@Rackme Rackme commented Sep 16, 2026

Copy link
Copy Markdown

What is this PR about?

A Docker-source application whose Docker Image carries no registry host is pulled from
Docker Hub regardless of the configured Registry URLbuildRemoteDocker passes the
image to docker pull verbatim and registryUrl only ever reaches docker login. The
deployment log shows Login Succeeded immediately followed by pull access denied, with
nothing saying the two commands addressed different registries.

This PR detects the mismatch before the shell script runs and fails with the correction:

❌ Docker image "app:latest" has no registry host, so Docker resolves it to
docker.io/library/app:latest — not to registry.example.com.

The Registry URL is only used for "docker login"; it is never added to the image name.
Put the registry in the Docker Image field instead:

  Docker Image:  registry.example.com/app:latest
  Registry URL:  registry.example.com

(add your namespace/project between the host and the image if your registry uses one)

The image is deliberately never rewritten. Prefixing it automatically would break the
legitimate "authenticate to a private registry, pull a public Hub image" setup, so the
mismatch is reported and the correction left to the user. Happy to switch to composition
if you'd rather — it's a one-line change in findRegistryMismatch.

Also included:

  • AuthConfig.serveraddress is reduced to a bare host. Swarm matches it against the
    registry host of the image on the target node, so a pasted
    https://registry.example.com/team/ could fail the node-side pull even once the
    build-server pull succeeded — and that's a different machine, since the service is created
    against application.serverId. Docker Hub is passed through untouched: its canonical auth
    key is the legacy https://index.docker.io/v1/, and normalising that to a hostname would
    store the credential under a key the Hub pull never looks up.
  • Form copy. A FormDescription on each field states which command it feeds, and the
    Docker Image one spells out that a private-registry image must carry its host. The
    placeholder stays a Docker Hub example (nginx:latest rather than the old node:16):
    the short form is correct for Hub, so putting a registry host in the placeholder would
    mislead the majority of users in the opposite direction. The rule belongs in the
    description, which can state the condition the placeholder cannot.

New pure module packages/server/src/utils/docker/registry-reference.ts; getImageRegistryHost
mirrors splitDockerDomain in distribution/reference (first component is a host when it
contains . or :, is localhost, or has an uppercase character).

Checklist

  • You created a dedicated branch based on the canary branch.
  • You have read the suggestions in the CONTRIBUTING.md file
  • I'm using Dokploy Cloud, thus cannot applied to my Org

Issues related (if applicable)

closes #5469

Notes for reviewers

No behaviour change for a working configuration: a fully-qualified image returns null from
findRegistryMismatch, and registryAuthAddress is a no-op on a value that is already a
bare host. The new refusal fires only on the pair that cannot work today.

findRegistryMismatch throws from buildRemoteDocker, so deployApplication's non-ExecError
branch base64-encodes it into the deployment log — the message lands where the user is already
looking.

RetriggerConfidence Score: 4/5

The PR is not safe to merge until it stops treating a public Docker Hub image combined with independent private-registry settings as a fatal mismatch.

Summary

This PR adds registry-reference parsing, rejects Docker-source image/registry mismatches before command execution, normalizes Swarm authentication addresses, updates form guidance, and adds unit tests.

  • Registry URLs are reduced to host-and-port values for Docker authentication while Docker Hub’s legacy address is preserved.
  • Docker-source deployments now receive an explanatory error when a short image reference is paired with a private Registry URL.
  • The new refusal also blocks valid public Docker Hub pulls when unrelated or stale private-registry settings remain configured.

Reviews (1) · Last reviewed commit: "fix(docker): report when a Docker-source..."

simonb and others added 3 commits September 16, 2026 12:13
…ocker Hub

The Docker source type exposes `dockerImage` and `registryUrl` as separate
fields, and `buildRemoteDocker` passes the image to `docker pull` verbatim —
`registryUrl` only ever reaches `docker login`. A reference with no registry
host is therefore resolved to Docker Hub however the Registry URL is
configured, which surfaces as a confusing pair of lines:

    Pulling amelio-dev:latest
    Login Succeeded
    Error response from daemon: pull access denied for amelio-dev, repository
    does not exist or may require 'docker login'

The login targets the right registry and the pull goes to Hub. Nothing in the
log says so, and the `node:16` placeholder actively suggests the short form.

Detect the mismatch before the shell script runs and fail with the correction,
naming both the reference Docker actually resolves and the value to use. The
image is deliberately never rewritten: prefixing it automatically would break
the legitimate "authenticate to a private registry, pull a public Hub image"
setup.

Also reduce the auth address to a bare host. `AuthConfig.serveraddress` is
matched against the registry host of the image on the Swarm node, so a pasted
`https://registry.example.com/team/` could fail the node-side pull even once
the build-server pull succeeded. Docker Hub is passed through untouched — its
canonical auth key is the legacy `https://index.docker.io/v1/`, and rewriting
that to a hostname would store the credential under a key the pull never
looks up.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ocker Hub

The Docker source type exposes `dockerImage` and `registryUrl` as separate
fields, and `buildRemoteDocker` passes the image to `docker pull` verbatim —
`registryUrl` only ever reaches `docker login`. A reference with no registry
host is therefore resolved to Docker Hub however the Registry URL is
configured, which surfaces as a confusing pair of lines:

    Pulling amelio-dev:latest
    Login Succeeded
    Error response from daemon: pull access denied for amelio-dev, repository
    does not exist or may require 'docker login'

The login targets the right registry and the pull goes to Hub. Nothing in the
log says so, and the `node:16` placeholder actively suggests the short form.

Detect the mismatch before the shell script runs and fail with the correction,
naming both the reference Docker actually resolves and the value to use. The
image is deliberately never rewritten: prefixing it automatically would break
the legitimate "authenticate to a private registry, pull a public Hub image"
setup.

Also reduce the auth address to a bare host. `AuthConfig.serveraddress` is
matched against the registry host of the image on the Swarm node, so a pasted
`https://registry.example.com/team/` could fail the node-side pull even once
the build-server pull succeeded. Docker Hub is passed through untouched — its
canonical auth key is the legacy `https://index.docker.io/v1/`, and rewriting
that to a hostname would store the credential under a key the pull never
looks up.
…ocker Hub

The Docker source type exposes `dockerImage` and `registryUrl` as separate
fields, and `buildRemoteDocker` passes the image to `docker pull` verbatim —
`registryUrl` only ever reaches `docker login`. A reference with no registry
host is therefore resolved to Docker Hub however the Registry URL is
configured, which surfaces as a confusing pair of lines:

    Pulling amelio-dev:latest
    Login Succeeded
    Error response from daemon: pull access denied for amelio-dev, repository
    does not exist or may require 'docker login'

The login targets the right registry and the pull goes to Hub. Nothing in the
log says so, and the `node:16` placeholder actively suggests the short form.

Detect the mismatch before the shell script runs and fail with the correction,
naming both the reference Docker actually resolves and the value to use. The
image is deliberately never rewritten: prefixing it automatically would break
the legitimate "authenticate to a private registry, pull a public Hub image"
setup.

Also reduce the auth address to a bare host. `AuthConfig.serveraddress` is
matched against the registry host of the image on the Swarm node, so a pasted
`https://registry.example.com/team/` could fail the node-side pull even once
the build-server pull succeeded. Docker Hub is passed through untouched — its
canonical auth key is the legacy `https://index.docker.io/v1/`, and rewriting
that to a hostname would store the credential under a key the pull never
looks up.
@Rackme
Rackme requested a review from Siumauricio as a code owner September 16, 2026 13:13
Comment on lines +21 to +24
const mismatch = findRegistryMismatch(dockerImage, registryUrl);
if (mismatch) {
throw new Error(mismatch);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Valid Hub pulls blocked

When an application uses a public Docker Hub image such as nginx:latest while retaining a non-Hub Registry URL and credentials, this check aborts the deployment before either login or pull runs. These settings are independent, and the previous flow could log in to the private registry before pulling the public Hub image, so applications with intentional or stale private-registry settings can no longer deploy a valid Hub image.

Knowledge Base Used: Build and Compose workflows

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Docker source: "Login Succeeded" then "pull access denied" — Registry URL never reaches the image name

1 participant