diff --git a/apps/dokploy/__test__/server/server-setup.test.ts b/apps/dokploy/__test__/server/server-setup.test.ts new file mode 100644 index 000000000..6a23aa8f9 --- /dev/null +++ b/apps/dokploy/__test__/server/server-setup.test.ts @@ -0,0 +1,98 @@ +import { execFileSync, execSync } from "node:child_process"; +import { chmodSync, mkdtempSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import path from "node:path"; +import { defaultCommand, reportDockerVersion } from "@dokploy/server"; +import { describe, expect, it } from "vitest"; + +const resolveBin = (name: string) => + execSync(`command -v ${name}`, { encoding: "utf8" }).trim(); + +/** + * Build a sandbox PATH so `command -v docker` only sees our fake docker + * binary (or nothing), regardless of what the host has installed. + */ +const makeSandbox = (dockerShim?: string) => { + const dir = mkdtempSync(path.join(tmpdir(), "dokploy-server-setup-")); + for (const tool of ["awk", "tr"]) { + const shim = path.join(dir, tool); + writeFileSync(shim, `#!/bin/sh\nexec ${resolveBin(tool)} "$@"\n`); + chmodSync(shim, 0o755); + } + if (dockerShim) { + const shim = path.join(dir, "docker"); + writeFileSync(shim, dockerShim); + chmodSync(shim, 0o755); + } + return dir; +}; + +const runReport = (sandboxPath: string) => { + const script = [ + "DOCKER_VERSION=28.5.0", + reportDockerVersion(), + 'echo "$DOCKER_VERSION_REPORT"', + ].join("\n"); + return execFileSync(resolveBin("bash"), ["-c", script], { + encoding: "utf8", + env: { ...process.env, PATH: sandboxPath }, + }) + .trim() + .split("\n") + .pop(); +}; + +describe("reportDockerVersion", () => { + it("reports the engine version when docker and its daemon are available", () => { + const sandbox = makeSandbox( + [ + "#!/bin/sh", + 'if [ "$1" = "--version" ]; then', + ' echo "Docker version 25.0.0, build aaaaaaa"', + " exit 0", + "fi", + 'if [ "$1" = "version" ]; then', + ' echo "29.4.3"', + " exit 0", + "fi", + "exit 1", + ].join("\n"), + ); + expect(runReport(sandbox)).toBe("29.4.3 (already installed)"); + }); + + it("falls back to the client version when the daemon is unreachable", () => { + const sandbox = makeSandbox( + [ + "#!/bin/sh", + 'if [ "$1" = "--version" ]; then', + ' echo "Docker version 29.4.3, build 055a478"', + " exit 0", + "fi", + 'echo "Cannot connect to the Docker daemon" >&2', + "exit 1", + ].join("\n"), + ); + expect(runReport(sandbox)).toBe("29.4.3 (already installed)"); + }); + + it("reports the pinned version to be installed when docker is missing", () => { + expect(runReport(makeSandbox())).toBe("28.5.0 (will be installed)"); + }); +}); + +describe("defaultCommand", () => { + it.each([false, true])( + "prints the detected Docker version in the setup banner (isBuildServer=%s)", + (isBuildServer) => { + const script = defaultCommand(isBuildServer); + expect(script).toContain(reportDockerVersion()); + expect(script).toContain( + 'echo "| Docker | $DOCKER_VERSION_REPORT"', + ); + expect(script).not.toContain( + 'echo "| Docker | $DOCKER_VERSION"', + ); + }, + ); +}); diff --git a/packages/server/src/setup/server-setup.ts b/packages/server/src/setup/server-setup.ts index e2d7fc3e5..7181880a4 100644 --- a/packages/server/src/setup/server-setup.ts +++ b/packages/server/src/setup/server-setup.ts @@ -106,6 +106,21 @@ export const serverSetup = async ( } }; +export const reportDockerVersion = () => ` +if command -v docker >/dev/null 2>&1; then + INSTALLED_DOCKER_VERSION=$(docker version --format '{{.Server.Version}}' 2>/dev/null || true) + if [ -z "$INSTALLED_DOCKER_VERSION" ]; then + INSTALLED_DOCKER_VERSION=$(docker --version 2>/dev/null | awk '{print $3}' | tr -d ',' || true) + fi + if [ -z "$INSTALLED_DOCKER_VERSION" ]; then + INSTALLED_DOCKER_VERSION="unknown" + fi + DOCKER_VERSION_REPORT="$INSTALLED_DOCKER_VERSION (already installed)" +else + DOCKER_VERSION_REPORT="$DOCKER_VERSION (will be installed)" +fi +`; + export const defaultCommand = (isBuildServer = false) => { const bashCommand = ` set -e; @@ -174,10 +189,11 @@ arch | ubuntu | debian | raspbian | centos | fedora | rhel | ol | rocky | sles | ;; esac +${reportDockerVersion()} echo -e "---------------------------------------------" echo "| CPU Architecture | $SYS_ARCH" echo "| Operating System | $OS_TYPE $OS_VERSION" -echo "| Docker | $DOCKER_VERSION" +echo "| Docker | $DOCKER_VERSION_REPORT" ${isBuildServer ? 'echo "| Server Type | Build Server"' : ""} echo -e "---------------------------------------------\n" echo -e "1. Installing required packages (curl, wget, git, jq, openssl). "