Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: added env support to Dokploy stack compose #637

Merged
merged 15 commits into from
Jan 31, 2025
Merged
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@ export const ComposeActions = ({ composeId }: Props) => {
Autodeploy {data?.autoDeploy && <CheckCircle2 className="size-4" />}
</Toggle>
<RedbuildCompose composeId={composeId} />
{data?.composeType === "docker-compose" && (
{["running", "done"].includes(data?.composeStatus || "") && (
<StopCompose composeId={composeId} />
)}

Original file line number Diff line number Diff line change
@@ -185,18 +185,12 @@ const Service = (
<div className="flex flex-row items-center justify-between w-full gap-4">
<TabsList
className={cn(
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
"md:grid md:w-fit max-md:overflow-y-scroll justify-start md:grid-cols-6",
data?.serverId ? "md:grid-cols-6" : "md:grid-cols-7",
data?.composeType === "docker-compose" ? "" : "md:grid-cols-6",
data?.serverId && data?.composeType === "stack"
? "md:grid-cols-5"
: "",
)}
>
<TabsTrigger value="general">General</TabsTrigger>
{data?.composeType === "docker-compose" && (
<TabsTrigger value="environment">Environment</TabsTrigger>
)}
<TabsTrigger value="environment">Environment</TabsTrigger>
{!data?.serverId && (
<TabsTrigger value="monitoring">Monitoring</TabsTrigger>
)}
11 changes: 11 additions & 0 deletions packages/server/src/services/compose.ts
Original file line number Diff line number Diff line change
@@ -476,6 +476,17 @@ export const stopCompose = async (composeId: string) => {
}
}

if (compose.composeType === "stack") {
if (compose.serverId) {
await execAsyncRemote(
compose.serverId,
`docker stack rm ${compose.appName}`,
);
} else {
await execAsync(`docker stack rm ${compose.appName}`);
}
}

await updateCompose(composeId, {
composeStatus: "idle",
});
43 changes: 40 additions & 3 deletions packages/server/src/utils/builders/compose.ts
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ import {
writeDomainsToComposeRemote,
} from "../docker/domain";
import { encodeBase64, prepareEnvironmentVariables } from "../docker/utils";
import { execAsyncRemote } from "../process/execAsync";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import { spawnAsync } from "../process/spawnAsync";

export type ComposeNested = InferResultType<
@@ -28,6 +28,7 @@ export const buildCompose = async (compose: ComposeNested, logPath: string) => {
const command = createCommand(compose);
await writeDomainsToCompose(compose, domains);
createEnvFile(compose);
await processComposeFile(compose);

const logContent = `
App Name: ${appName}
@@ -84,6 +85,7 @@ export const getBuildComposeCommand = async (
const command = createCommand(compose);
const envCommand = getCreateEnvFileCommand(compose);
const projectPath = join(COMPOSE_PATH, compose.appName, "code");
const processComposeFileCommand = getProcessComposeFileCommand(compose);

const newCompose = await writeDomainsToComposeRemote(
compose,
@@ -119,6 +121,8 @@ Compose Type: ${composeType} ✅`;
cd "${projectPath}";
${processComposeFileCommand}
docker ${command.split(" ").join(" ")} >> "${logPath}" 2>&1 || { echo "Error: ❌ Docker command failed" >> "${logPath}"; exit 1; }
echo "Docker Compose Deployed: ✅" >> "${logPath}"
@@ -144,8 +148,19 @@ const sanitizeCommand = (command: string) => {
export const createCommand = (compose: ComposeNested) => {
const { composeType, appName, sourceType } = compose;

const path =
sourceType === "raw" ? "docker-compose.yml" : compose.composePath;
let path = "";

if (sourceType === "raw") {
path =
composeType === "stack"
? "docker-compose.processed.yml"
: "docker-compose.yml";
} else {
path = compose.composePath;
}

console.log(path);

let command = "";

if (composeType === "docker-compose") {
@@ -188,6 +203,28 @@ const createEnvFile = (compose: ComposeNested) => {
writeFileSync(envFilePath, envFileContent);
};

export const processComposeFile = async (compose: ComposeNested) => {
const { COMPOSE_PATH } = paths();
if (compose.composeType === "stack") {
const command = getProcessComposeFileCommand(compose);
await execAsync(command, {
cwd: join(COMPOSE_PATH, compose.appName, "code"),
});
}
};

export const getProcessComposeFileCommand = (compose: ComposeNested) => {
const { composeType } = compose;

let command = "";

if (composeType === "stack") {
command = `export $(grep -v '^#' .env | xargs) && docker stack config -c docker-compose.yml > docker-compose.processed.yml`;
}

return command;
};

export const getCreateEnvFileCommand = (compose: ComposeNested) => {
const { COMPOSE_PATH } = paths(true);
const { env, composePath, appName } = compose;