Skip to content

#2345: Fix DOCKER_EDITION ignored on Linux - #2362

Open
Hiepiscus wants to merge 8 commits into
devonfw:mainfrom
Hiepiscus:2345-docker-edition-ignored-linux
Open

#2345: Fix DOCKER_EDITION ignored on Linux#2362
Hiepiscus wants to merge 8 commits into
devonfw:mainfrom
Hiepiscus:2345-docker-edition-ignored-linux

Conversation

@Hiepiscus

@Hiepiscus Hiepiscus commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

This PR fixes #2345

On Linux, setting DOCKER_EDITION=docker had no effect because the Docker Desktop URL metadata did not contain a Linux download URL. As a result, Docker Desktop could not be selected and Rancher Desktop was installed instead.

While adding Linux support, the Docker Desktop URL updater also had to be adjusted because the previous release notes URL no longer provided the expected content.

Docker Desktop installation on Linux

Docker Desktop requires a different installation than Rancher Desktop. Rancher Desktop is available as a package from its configured package repository and can therefore be installed directly by its package name.

image

Docker Desktop, however is distributed as a separate Debian package. According to the official Docker Desktop , the Docker package repository must first be configured, the Docker Desktop .deb package must then be downloaded separately, and finally the local package must be installed using:

image

Implemented changes:

  • Add Linux support for DockerDesktopUrlUpdater
  • Enable Docker.java to resolve the docker edition on Linux when DOCKER_EDITION=docker is configured.
  • Update the Docker Desktop release notes URL from docs.docker.com/desktop/release-notes to docs.docker.com/desktop/release-notes.md.
  • Adapt the regular expression to extract the Docker Desktop build code from the Markdown release notes.
  • Use the extracted build code to generate the Linux download URL.
  • Download the selected Docker Desktop Debian package through the configured ToolRepository.
  • Add a dedicated package manager command to install the downloaded .deb file
  • Keep docker-desktop as the native package name for version detection and uninstallation.

Testing instructions

  1. Create a local urls-status directory and clone the ide-urls-status repository:
    git clone https://github.com/devonfw/ide-urls-status.git <path-to-ide-urls-status>
  2. Run the DockerDesktopUrlUpdater locally by passing the paths to your local ide-urls and ide-urls-status repositories:
    UpdateInitiator <path-to-ide-urls> <path-to-ide-urls-status> PT1H docker
  3. Verify that the generated Docker Desktop metadata contains a Linux download URL.
  4. Commit the generated metadata in the local ide-urls repository so that it remains available when IDEasy installs Docker Desktop:
cd <path-to-ide-urls>
git add .
git commit -m "Add Docker Desktop metadata for Linux"
  1. On a Linux system, run:
    • Run ide set-edition docker docker
    • Run ide install docker
  2. Verify that Docker Desktop is selected and installed instead of Rancher Desktop.
    • dpkg-query -W docker-desktop
  3. Uninstall Docker Desktop and verify docker-desktop was removed:
    • ide uninstall docker
    • dpkg-query -W docker-desktop

Checklist for this PR

Make sure everything is checked before merging this PR. For further info please also see
our DoD.

  • When running mvn clean test locally all tests pass and build is successful
  • PR title is of the form #«issue-id»: «brief summary» (e.g. #921: fixed setup.bat and not feature/921 fixed setup.bat). If no issue ID exists, title only.
  • PR top-level comment summaries what has been done and contains link to addressed issue(s)
  • PR and issue(s) have suitable labels
  • Issue is set to In Progress and assigned to you or there is no issue (might happen for very small PRs)
  • You followed all coding conventions
  • You have added the issue implemented by your PR in CHANGELOG.adoc unless issue is labelled
    with internal
  • You have not changed any dependency in pom.xml files or otherwise if runtime dependencies changed, you have updated our LICENSE.asciidoc
  • You have formulated clear instructions on how to test your contribution under "Testing instructions"

@github-project-automation github-project-automation Bot moved this to 🆕 New in IDEasy board Aug 24, 2026
@Hiepiscus Hiepiscus self-assigned this Aug 24, 2026
@Hiepiscus Hiepiscus added urls ide-urls repo and related processes and features docker docker and esp. DockerDesktop linux specific for linux OS (debian, ubunutu, suse, etc.) install installation process of IDE + tools and install commandlet labels Aug 24, 2026
@Hiepiscus Hiepiscus moved this from 🆕 New to Team Review in IDEasy board Aug 24, 2026
@Hiepiscus Hiepiscus changed the title #2345: docker edition ignored linux #2345: Fix DOCKER_EDITION ignored on Linux Aug 24, 2026
@coveralls

coveralls commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 32823580782

Warning

Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes.
Quick fix: rebase this PR. Learn more →

Coverage decreased (-0.05%) to 73.426%

Details

  • Coverage decreased (-0.05%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 138 coverage regressions across 6 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

138 previously-covered lines in 6 files lost coverage.

File Lines Losing Coverage Coverage
com/devonfw/tools/ide/context/AbstractIdeContext.java 77 70.72%
com/devonfw/tools/ide/tool/docker/Docker.java 43 5.68%
com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java 11 18.18%
com/devonfw/tools/ide/cli/Ideasy.java 5 50.68%
com/devonfw/tools/ide/cli/CliException.java 1 85.71%
com/devonfw/tools/ide/tool/dotnet/DotNet.java 1 83.33%

Coverage Stats

Coverage Status
Relevant Lines: 18057
Covered Lines: 13859
Line Coverage: 76.75%
Relevant Branches: 8017
Covered Branches: 5286
Branch Coverage: 65.93%
Branches in Coverage %: Yes
Coverage Strength: 3.27 hits per line

💛 - Coveralls

@Hiepiscus Hiepiscus left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The default native package installation is implemented in GlobalToolCommandlet#getInstallPackageManagerCommands. It retrieves the native packages defined by the tool and passes the resolved IDEasy version to each package installation:

protected List<PackageManagerCommand> getInstallPackageManagerCommands(VersionIdentifier resolvedVersion) {
String version = (resolvedVersion == null) ? null : resolvedVersion.toString();
return getNativePackages().stream().map(nativePackage -> nativePackage.install(version)).toList();
}

This behavior works for packages that are installed from a package repository such as Rancher Desktop. The package name and resolved version can be combined to create a version specific package.

For APT, NativePackageManager#getPackageSpec creates this package specification by appending the resolved version and a wildcard to the package name:

public String getPackageSpec(String pkg, String version) {
if ((version == null) || version.isBlank()) {
return pkg;
}
String spec = pkg + this.versionSeparator + version + this.versionWildCard;
if (this.versionWildCard.isEmpty()) {
return spec;
}
return "'" + spec + "'";
}

For a regular repository package, this produces a valid package:
rancher-desktop=1.20.0*

Docker Desktop requires a different installation because it is distributed as a separate Debian package. Applying the default version logic to a downloaded local file would produce an invalid APT argument:
/tmp/docker-desktop-amd64.deb=4.34.0*

}

ToolRepository toolRepository = this.context.getDefaultToolRepository();
Path downloadedDeb = toolRepository.download(this.tool, EDITION_DOCKER, resolvedVersion, this);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

getInstallPackageManagerCommands overrides the default installation only for the docker edition. The implementation uses the configured ToolRepository to download the Debian package matching the resolved Docker Desktop version

+ "sudo tee /etc/apt/sources.list.d/docker.list > /dev/null",
"sudo apt update"
),
List.of()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Using the path returned by ToolRepository ensures that installs the exact artifact resolved through the generated ide-urls metadata instead of downloading the latest unversioned Docker Desktop package.

),
List.of()
);
return List.of(dockerDesktopInstallPackage.install(null));

@Hiepiscus Hiepiscus Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The package is installed with install(null), which is intentional. It prevents NativePackageManager#getPackageSpec from appending the resolved version to the local .deb path (e.g. /tmp/docker-desktop-amd64.deb instead of /tmp/docker-desktop-amd64.deb=4.34.0*).

)
)
);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The existing Rancher Desktop installation remains unchanged.

The regular NativePackage definition for the Docker edition is still required. This definition uses the installed package name docker-desktop, rather than the temporary download path. The package name is needed for package-related operations after installation, especially uninstallation. This allows to create the correct uninstall command:
sudo apt -y autoremove --purge docker-desktop

@QuangAnhLe
QuangAnhLe removed their request for review August 27, 2026 11:06
Comment on lines 71 to +87
@Override
protected List<NativePackage> getNativePackages() {

if (EDITION_DOCKER.equals(getConfiguredEdition())) {
return List.of(
new NativePackage(
NativePackageManager.APT,
List.of("docker-desktop"),
List.of("--allow-downgrades"),
List.of(),
List.of(
"sudo rm -f /etc/apt/sources.list.d/docker.list",
"sudo rm -f /etc/apt/keyrings/docker.asc"
)
)
);
}

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.

IMHO we should not download the package as part of getPackageManagerCommands(). It feels a bit unexpected to perform a side effect while merely resolving the package manager commands.

Instead, we could download the .deb earlier as part of the installation flow (for example by overriding doInstall()), store the downloaded path, and then pass that path through getNativePackages() just like we do for other native packages.

Something along these lines:

Suggested change
@Override
protected List<NativePackage> getNativePackages() {
if (EDITION_DOCKER.equals(getConfiguredEdition())) {
return List.of(
new NativePackage(
NativePackageManager.APT,
List.of("docker-desktop"),
List.of("--allow-downgrades"),
List.of(),
List.of(
"sudo rm -f /etc/apt/sources.list.d/docker.list",
"sudo rm -f /etc/apt/keyrings/docker.asc"
)
)
);
}
private Path downloadedDebPackageForDocker;
@Override
protected ToolInstallation doInstall(ToolInstallRequest request) {
if (EDITION_DOCKER.equals(getConfiguredEdition())) {
downloadDebPackageStepAndSetPackagePath(request.getRequested().getResolvedVersion());
}
return super.doInstall(request);
}
private void downloadDebPackageStepAndSetPackagePath(VersionIdentifier resolvedVersion) {
ToolRepository toolRepository = this.context.getDefaultToolRepository();
this.downloadedDebPackageForDocker = toolRepository.download(this.tool, EDITION_DOCKER, resolvedVersion, this);
}
@Override
protected List<NativePackage> getNativePackages() {
if (EDITION_DOCKER.equals(getConfiguredEdition())) {
return List.of(
new NativePackage(
NativePackageManager.APT,
List.of(downloadedDebPackageForDocker.toString()),
List.of("--allow-downgrades"),
List.of(
"sudo install -m 0755 -d /etc/apt/keyrings",
"sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc",
"sudo chmod a+r /etc/apt/keyrings/docker.asc",
"echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] "
+ "https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \\\"$VERSION_CODENAME\\\") stable\" | "
+ "sudo tee /etc/apt/sources.list.d/docker.list > /dev/null",
"sudo apt update"
),
List.of(
"sudo rm -f /etc/apt/sources.list.d/docker.list",
"sudo rm -f /etc/apt/keyrings/docker.asc"
)
);
}

Comment on lines +117 to +141
@Override
protected List<PackageManagerCommand> getInstallPackageManagerCommands(VersionIdentifier resolvedVersion) {
if (!EDITION_DOCKER.equals(getConfiguredEdition())) {
return super.getInstallPackageManagerCommands(resolvedVersion);
}

ToolRepository toolRepository = this.context.getDefaultToolRepository();
Path downloadedDeb = toolRepository.download(this.tool, EDITION_DOCKER, resolvedVersion, this);

NativePackage dockerDesktopInstallPackage = new NativePackage(
NativePackageManager.APT,
List.of(downloadedDeb.toString()),
List.of("--allow-downgrades"),
List.of(
"sudo install -m 0755 -d /etc/apt/keyrings",
"sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc",
"sudo chmod a+r /etc/apt/keyrings/docker.asc",
"echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] "
+ "https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \\\"$VERSION_CODENAME\\\") stable\" | "
+ "sudo tee /etc/apt/sources.list.d/docker.list > /dev/null",
"sudo apt update"
),
List.of()
);
return List.of(dockerDesktopInstallPackage.install(null));

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.

If the previous changes (https://github.com/devonfw/IDEasy/pull/2362/changes#r3871801542) have already been applied, these lines should no longer be necessary:

Suggested change
@Override
protected List<PackageManagerCommand> getInstallPackageManagerCommands(VersionIdentifier resolvedVersion) {
if (!EDITION_DOCKER.equals(getConfiguredEdition())) {
return super.getInstallPackageManagerCommands(resolvedVersion);
}
ToolRepository toolRepository = this.context.getDefaultToolRepository();
Path downloadedDeb = toolRepository.download(this.tool, EDITION_DOCKER, resolvedVersion, this);
NativePackage dockerDesktopInstallPackage = new NativePackage(
NativePackageManager.APT,
List.of(downloadedDeb.toString()),
List.of("--allow-downgrades"),
List.of(
"sudo install -m 0755 -d /etc/apt/keyrings",
"sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc",
"sudo chmod a+r /etc/apt/keyrings/docker.asc",
"echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] "
+ "https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \\\"$VERSION_CODENAME\\\") stable\" | "
+ "sudo tee /etc/apt/sources.list.d/docker.list > /dev/null",
"sudo apt update"
),
List.of()
);
return List.of(dockerDesktopInstallPackage.install(null));

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

Labels

docker docker and esp. DockerDesktop install installation process of IDE + tools and install commandlet linux specific for linux OS (debian, ubunutu, suse, etc.) urls ide-urls repo and related processes and features

Projects

Status: Team Review

Development

Successfully merging this pull request may close these issues.

DOCKER_EDITION ignored on Linux

4 participants