mirror of
https://github.com/dokploy/dokploy.git
synced 2026-06-13 19:09:49 +00:00
fix: preserve HOME in compose deploy so --with-registry-auth can read docker config (#4485)
The compose/stack deploy command runs under `env -i PATH="$PATH"`, which clears the environment except for PATH. That strips HOME, so when the generated command is `docker stack deploy --prune --with-registry-auth` the docker CLI cannot resolve `~/.docker/config.json` (e.g. `/root/.docker/config.json`) and ships no registry credentials to the swarm. Private-registry images then fail to pull on the nodes: image registry.example.com/... could not be accessed on a registry to record its digest. Each node will access ... independently while the deploy still logs "Docker Compose Deployed: ✅". Keep PATH isolation but preserve HOME so docker can read its config for both `stack deploy --with-registry-auth` and `compose up -d --build`. Add a regression test asserting the generated command preserves `HOME="$HOME"` for both stack and docker-compose deploys. Fixes #4401 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { getBuildComposeCommand } from "@dokploy/server/utils/builders/compose";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
// Isolate the command builder from the compose-file I/O performed by
|
||||
// writeDomainsToCompose; we only care about the docker invocation it emits.
|
||||
vi.mock("@dokploy/server/utils/docker/domain", () => ({
|
||||
writeDomainsToCompose: vi.fn().mockResolvedValue(""),
|
||||
}));
|
||||
|
||||
const baseCompose = {
|
||||
appName: "my-app",
|
||||
sourceType: "raw",
|
||||
command: "",
|
||||
composePath: "docker-compose.yml",
|
||||
composeType: "stack",
|
||||
isolatedDeployment: false,
|
||||
randomize: false,
|
||||
suffix: "",
|
||||
serverId: null,
|
||||
env: "",
|
||||
mounts: [],
|
||||
domains: [],
|
||||
environment: { project: { env: "" }, env: "" },
|
||||
} as unknown as Parameters<typeof getBuildComposeCommand>[0];
|
||||
|
||||
// Regression coverage for #4401: the deploy command runs under `env -i`, which
|
||||
// clears the environment except for the vars listed explicitly. HOME must be
|
||||
// preserved so docker can resolve ~/.docker/config.json — otherwise
|
||||
// `docker stack deploy --with-registry-auth` ships no credentials to the swarm
|
||||
// and private-registry images fail to pull.
|
||||
describe("getBuildComposeCommand registry auth (#4401)", () => {
|
||||
it("preserves HOME for swarm stack deploys", async () => {
|
||||
const command = await getBuildComposeCommand({
|
||||
...baseCompose,
|
||||
composeType: "stack",
|
||||
});
|
||||
|
||||
expect(command).toContain("stack deploy");
|
||||
expect(command).toContain("--with-registry-auth");
|
||||
expect(command).toContain('env -i PATH="$PATH" HOME="$HOME"');
|
||||
});
|
||||
|
||||
it("preserves HOME for docker compose deploys", async () => {
|
||||
const command = await getBuildComposeCommand({
|
||||
...baseCompose,
|
||||
composeType: "docker-compose",
|
||||
});
|
||||
|
||||
expect(command).toContain("compose -p my-app");
|
||||
expect(command).toContain('env -i PATH="$PATH" HOME="$HOME"');
|
||||
});
|
||||
});
|
||||
@@ -54,7 +54,7 @@ Compose Type: ${composeType} ✅`;
|
||||
cd "${projectPath}";
|
||||
|
||||
${compose.isolatedDeployment ? `docker network inspect ${compose.appName} >/dev/null 2>&1 || docker network create ${compose.composeType === "stack" ? "--driver overlay" : ""} --attachable ${compose.appName}` : ""}
|
||||
env -i PATH="$PATH" ${exportEnvCommand} docker ${command.split(" ").join(" ")} 2>&1 || { echo "Error: ❌ Docker command failed"; exit 1; }
|
||||
env -i PATH="$PATH" HOME="$HOME" ${exportEnvCommand} docker ${command.split(" ").join(" ")} 2>&1 || { echo "Error: ❌ Docker command failed"; exit 1; }
|
||||
${compose.isolatedDeployment ? `docker network connect ${compose.appName} $(docker ps --filter "name=dokploy-traefik" -q) >/dev/null 2>&1` : ""}
|
||||
|
||||
echo "Docker Compose Deployed: ✅";
|
||||
|
||||
Reference in New Issue
Block a user