Merge pull request #5201 from Dokploy/fix/compose-git-mounts-5181

fix: resolve relative bind mounts against code dir for git-based compose deploys
This commit is contained in:
Mauricio Siu 2026-08-27 09:15:38 -06:00 committed by GitHub
commit ca3da4dc5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 70 additions and 5 deletions

View File

@ -0,0 +1,58 @@
import { createCommand } from "@dokploy/server/utils/builders/compose";
import { describe, expect, it } from "vitest";
const base = {
composeType: "docker-compose" as const,
appName: "compose-app",
sourceType: "github" as const,
command: "",
};
describe("compose createCommand --project-directory", () => {
it("pins --project-directory to the code dir when composePath is nested", () => {
const cmd = createCommand(
{ ...base, composePath: "./deploy/docker-compose.yml" } as any,
"/etc/dokploy/compose/compose-app/code",
);
expect(cmd).toContain(
"--project-directory /etc/dokploy/compose/compose-app/code",
);
expect(cmd).toContain("-f ./deploy/docker-compose.yml");
});
it("omits --project-directory when no projectPath is passed", () => {
const cmd = createCommand({
...base,
composePath: "./deploy/docker-compose.yml",
} as any);
expect(cmd).not.toContain("--project-directory");
});
it("does not add --project-directory to stack deploy (unsupported flag)", () => {
const cmd = createCommand(
{
...base,
composeType: "stack",
composePath: "./deploy/docker-compose.yml",
} as any,
"/etc/dokploy/compose/compose-app/code",
);
expect(cmd).not.toContain("--project-directory");
expect(cmd.startsWith("stack deploy")).toBe(true);
});
it("keeps raw sourceType resolving from the code dir (root docker-compose.yml)", () => {
const cmd = createCommand(
{ ...base, sourceType: "raw", composePath: "docker-compose.yml" } as any,
"/etc/dokploy/compose/compose-app/code",
);
expect(cmd).toContain(
"--project-directory /etc/dokploy/compose/compose-app/code",
);
expect(cmd).toContain("-f docker-compose.yml");
});
});

View File

@ -1,3 +1,4 @@
import { join } from "node:path";
import {
addDomainToCompose,
clearOldDeployments,
@ -32,6 +33,7 @@ import {
updateCompose,
updateDeploymentStatus,
} from "@dokploy/server";
import { paths } from "@dokploy/server/constants";
import { db } from "@dokploy/server/db";
import { canEditDeployGitSource } from "@dokploy/server/services/git-provider";
import {
@ -547,7 +549,9 @@ export const composeRouter = createTRPCRouter({
service: ["create"],
});
const compose = await findComposeById(input.composeId);
const command = createCommand(compose);
const { COMPOSE_PATH } = paths(!!compose.serverId);
const projectPath = join(COMPOSE_PATH, compose.appName, "code");
const command = createCommand(compose, projectPath);
return `docker ${command}`;
}),
refreshToken: protectedProcedure

View File

@ -21,11 +21,11 @@ export const getBuildComposeCommand = async (rawCompose: ComposeNested) => {
const compose = await withResolvedVaultRefs(rawCompose);
const { COMPOSE_PATH } = paths(!!compose.serverId);
const { sourceType, appName, mounts, composeType, domains } = compose;
const command = createCommand(compose);
const projectPath = join(COMPOSE_PATH, compose.appName, "code");
const command = createCommand(compose, projectPath);
const envCommand = compose.createEnvFile
? getCreateEnvFileCommand(compose)
: "";
const projectPath = join(COMPOSE_PATH, compose.appName, "code");
const exportEnvCommand = getExportEnvCommand(compose);
const newCompose = await writeDomainsToCompose(compose, domains);
@ -119,7 +119,7 @@ const sanitizeCommand = (command: string) => {
return restCommand.join(" ");
};
export const createCommand = (compose: ComposeNested) => {
export const createCommand = (compose: ComposeNested, projectPath?: string) => {
const { composeType, appName, sourceType } = compose;
if (compose.command) {
return `${sanitizeCommand(compose.command)}`;
@ -130,7 +130,10 @@ export const createCommand = (compose: ComposeNested) => {
let command = "";
if (composeType === "docker-compose") {
command = `compose -p ${quote([appName])} -f ${quote([path])} up -d --build --remove-orphans`;
const projectDirectoryFlag = projectPath
? `--project-directory ${quote([projectPath])} `
: "";
command = `compose -p ${quote([appName])} ${projectDirectoryFlag}-f ${quote([path])} up -d --build --remove-orphans`;
} else if (composeType === "stack") {
command = `stack deploy -c ${quote([path])} ${quote([appName])} --prune --with-registry-auth`;
}