mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Merge pull request #1502 from Dokploy/1493-railpack-spawns-multiple-build-kit-containers
1493 railpack spawns multiple build kit containers
This commit is contained in:
@@ -136,26 +136,24 @@ export const getContainersByAppNameMatch = async (
|
|||||||
result = stdout.trim().split("\n");
|
result = stdout.trim().split("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
const containers = result
|
const containers = result.map((line) => {
|
||||||
.map((line) => {
|
const parts = line.split(" | ");
|
||||||
const parts = line.split(" | ");
|
const containerId = parts[0]
|
||||||
const containerId = parts[0]
|
? parts[0].replace("CONTAINER ID : ", "").trim()
|
||||||
? parts[0].replace("CONTAINER ID : ", "").trim()
|
: "No container id";
|
||||||
: "No container id";
|
const name = parts[1]
|
||||||
const name = parts[1]
|
? parts[1].replace("Name: ", "").trim()
|
||||||
? parts[1].replace("Name: ", "").trim()
|
: "No container name";
|
||||||
: "No container name";
|
|
||||||
|
|
||||||
const state = parts[2]
|
const state = parts[2]
|
||||||
? parts[2].replace("State: ", "").trim()
|
? parts[2].replace("State: ", "").trim()
|
||||||
: "No state";
|
: "No state";
|
||||||
return {
|
return {
|
||||||
containerId,
|
containerId,
|
||||||
name,
|
name,
|
||||||
state,
|
state,
|
||||||
};
|
};
|
||||||
})
|
});
|
||||||
.sort((a, b) => a.name.localeCompare(b.name));
|
|
||||||
|
|
||||||
return containers || [];
|
return containers || [];
|
||||||
} catch (_error) {}
|
} catch (_error) {}
|
||||||
@@ -192,30 +190,28 @@ export const getStackContainersByAppName = async (
|
|||||||
result = stdout.trim().split("\n");
|
result = stdout.trim().split("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
const containers = result
|
const containers = result.map((line) => {
|
||||||
.map((line) => {
|
const parts = line.split(" | ");
|
||||||
const parts = line.split(" | ");
|
const containerId = parts[0]
|
||||||
const containerId = parts[0]
|
? parts[0].replace("CONTAINER ID : ", "").trim()
|
||||||
? parts[0].replace("CONTAINER ID : ", "").trim()
|
: "No container id";
|
||||||
: "No container id";
|
const name = parts[1]
|
||||||
const name = parts[1]
|
? parts[1].replace("Name: ", "").trim()
|
||||||
? parts[1].replace("Name: ", "").trim()
|
: "No container name";
|
||||||
: "No container name";
|
|
||||||
|
|
||||||
const state = parts[2]
|
const state = parts[2]
|
||||||
? parts[2].replace("State: ", "").trim().toLowerCase()
|
? parts[2].replace("State: ", "").trim().toLowerCase()
|
||||||
: "No state";
|
: "No state";
|
||||||
const node = parts[3]
|
const node = parts[3]
|
||||||
? parts[3].replace("Node: ", "").trim()
|
? parts[3].replace("Node: ", "").trim()
|
||||||
: "No specific node";
|
: "No specific node";
|
||||||
return {
|
return {
|
||||||
containerId,
|
containerId,
|
||||||
name,
|
name,
|
||||||
state,
|
state,
|
||||||
node,
|
node,
|
||||||
};
|
};
|
||||||
})
|
});
|
||||||
.sort((a, b) => a.name.localeCompare(b.name));
|
|
||||||
|
|
||||||
return containers || [];
|
return containers || [];
|
||||||
} catch (_error) {}
|
} catch (_error) {}
|
||||||
@@ -253,31 +249,29 @@ export const getServiceContainersByAppName = async (
|
|||||||
result = stdout.trim().split("\n");
|
result = stdout.trim().split("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
const containers = result
|
const containers = result.map((line) => {
|
||||||
.map((line) => {
|
const parts = line.split(" | ");
|
||||||
const parts = line.split(" | ");
|
const containerId = parts[0]
|
||||||
const containerId = parts[0]
|
? parts[0].replace("CONTAINER ID : ", "").trim()
|
||||||
? parts[0].replace("CONTAINER ID : ", "").trim()
|
: "No container id";
|
||||||
: "No container id";
|
const name = parts[1]
|
||||||
const name = parts[1]
|
? parts[1].replace("Name: ", "").trim()
|
||||||
? parts[1].replace("Name: ", "").trim()
|
: "No container name";
|
||||||
: "No container name";
|
|
||||||
|
|
||||||
const state = parts[2]
|
const state = parts[2]
|
||||||
? parts[2].replace("State: ", "").trim().toLowerCase()
|
? parts[2].replace("State: ", "").trim().toLowerCase()
|
||||||
: "No state";
|
: "No state";
|
||||||
|
|
||||||
const node = parts[3]
|
const node = parts[3]
|
||||||
? parts[3].replace("Node: ", "").trim()
|
? parts[3].replace("Node: ", "").trim()
|
||||||
: "No specific node";
|
: "No specific node";
|
||||||
return {
|
return {
|
||||||
containerId,
|
containerId,
|
||||||
name,
|
name,
|
||||||
state,
|
state,
|
||||||
node,
|
node,
|
||||||
};
|
};
|
||||||
})
|
});
|
||||||
.sort((a, b) => a.name.localeCompare(b.name));
|
|
||||||
|
|
||||||
return containers || [];
|
return containers || [];
|
||||||
} catch (_error) {}
|
} catch (_error) {}
|
||||||
@@ -318,25 +312,23 @@ export const getContainersByAppLabel = async (
|
|||||||
|
|
||||||
const lines = stdout.trim().split("\n");
|
const lines = stdout.trim().split("\n");
|
||||||
|
|
||||||
const containers = lines
|
const containers = lines.map((line) => {
|
||||||
.map((line) => {
|
const parts = line.split(" | ");
|
||||||
const parts = line.split(" | ");
|
const containerId = parts[0]
|
||||||
const containerId = parts[0]
|
? parts[0].replace("CONTAINER ID : ", "").trim()
|
||||||
? parts[0].replace("CONTAINER ID : ", "").trim()
|
: "No container id";
|
||||||
: "No container id";
|
const name = parts[1]
|
||||||
const name = parts[1]
|
? parts[1].replace("Name: ", "").trim()
|
||||||
? parts[1].replace("Name: ", "").trim()
|
: "No container name";
|
||||||
: "No container name";
|
const state = parts[2]
|
||||||
const state = parts[2]
|
? parts[2].replace("State: ", "").trim()
|
||||||
? parts[2].replace("State: ", "").trim()
|
: "No state";
|
||||||
: "No state";
|
return {
|
||||||
return {
|
containerId,
|
||||||
containerId,
|
name,
|
||||||
name,
|
state,
|
||||||
state,
|
};
|
||||||
};
|
});
|
||||||
})
|
|
||||||
.sort((a, b) => a.name.localeCompare(b.name));
|
|
||||||
|
|
||||||
return containers || [];
|
return containers || [];
|
||||||
} catch (_error) {}
|
} catch (_error) {}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import type { ApplicationNested } from ".";
|
|||||||
import { prepareEnvironmentVariables } from "../docker/utils";
|
import { prepareEnvironmentVariables } from "../docker/utils";
|
||||||
import { getBuildAppDirectory } from "../filesystem/directory";
|
import { getBuildAppDirectory } from "../filesystem/directory";
|
||||||
import { spawnAsync } from "../process/spawnAsync";
|
import { spawnAsync } from "../process/spawnAsync";
|
||||||
import { execAsync } from "../process/execAsync";
|
|
||||||
|
|
||||||
export const buildRailpack = async (
|
export const buildRailpack = async (
|
||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
@@ -17,32 +16,62 @@ export const buildRailpack = async (
|
|||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Ensure buildkit container is running, create if it doesn't exist
|
// First prepare the build plan and info
|
||||||
await execAsync(
|
const prepareArgs = [
|
||||||
"docker container inspect buildkit >/dev/null 2>&1 || docker run --rm --privileged -d --name buildkit moby/buildkit",
|
"prepare",
|
||||||
);
|
buildAppDirectory,
|
||||||
|
"--plan-out",
|
||||||
|
`${buildAppDirectory}/railpack-plan.json`,
|
||||||
|
"--info-out",
|
||||||
|
`${buildAppDirectory}/railpack-info.json`,
|
||||||
|
];
|
||||||
|
|
||||||
// Build the application using railpack
|
// Add environment variables to prepare command
|
||||||
const args = ["build", buildAppDirectory, "--name", appName];
|
|
||||||
|
|
||||||
// Add environment variables
|
|
||||||
for (const env of envVariables) {
|
for (const env of envVariables) {
|
||||||
args.push("--env", env);
|
prepareArgs.push("--env", env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run prepare command
|
||||||
|
await spawnAsync("railpack", prepareArgs, (data) => {
|
||||||
|
if (writeStream.writable) {
|
||||||
|
writeStream.write(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Build with BuildKit using the Railpack frontend
|
||||||
|
const buildArgs = [
|
||||||
|
"buildx",
|
||||||
|
"build",
|
||||||
|
"--build-arg",
|
||||||
|
"BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v0.0.55",
|
||||||
|
"-f",
|
||||||
|
`${buildAppDirectory}/railpack-plan.json`,
|
||||||
|
"--output",
|
||||||
|
`type=docker,name=${appName}`,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add secrets properly formatted
|
||||||
|
const env: { [key: string]: string } = {};
|
||||||
|
for (const envVar of envVariables) {
|
||||||
|
const [key, value] = envVar.split("=");
|
||||||
|
if (key && value) {
|
||||||
|
buildArgs.push("--secret", `id=${key},env=${key}`);
|
||||||
|
env[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildArgs.push(buildAppDirectory);
|
||||||
|
|
||||||
await spawnAsync(
|
await spawnAsync(
|
||||||
"railpack",
|
"docker",
|
||||||
args,
|
buildArgs,
|
||||||
(data) => {
|
(data) => {
|
||||||
if (writeStream.writable) {
|
if (writeStream.writable) {
|
||||||
writeStream.write(data);
|
writeStream.write(data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
env: {
|
env: { ...process.env, ...env },
|
||||||
...process.env,
|
|
||||||
BUILDKIT_HOST: "docker-container://buildkit",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -63,25 +92,65 @@ export const getRailpackCommand = (
|
|||||||
application.project.env,
|
application.project.env,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Build the application using railpack
|
// Prepare command
|
||||||
const args = ["build", buildAppDirectory, "--name", appName];
|
const prepareArgs = [
|
||||||
|
"prepare",
|
||||||
|
buildAppDirectory,
|
||||||
|
"--plan-out",
|
||||||
|
`${buildAppDirectory}/railpack-plan.json`,
|
||||||
|
"--info-out",
|
||||||
|
`${buildAppDirectory}/railpack-info.json`,
|
||||||
|
];
|
||||||
|
|
||||||
// Add environment variables
|
|
||||||
for (const env of envVariables) {
|
for (const env of envVariables) {
|
||||||
args.push("--env", env);
|
prepareArgs.push("--env", env);
|
||||||
}
|
}
|
||||||
|
|
||||||
const command = `railpack ${args.join(" ")}`;
|
// Build command
|
||||||
|
const buildArgs = [
|
||||||
|
"buildx",
|
||||||
|
"build",
|
||||||
|
"--build-arg",
|
||||||
|
"BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v0.0.55",
|
||||||
|
"-f",
|
||||||
|
`${buildAppDirectory}/railpack-plan.json`,
|
||||||
|
"--output",
|
||||||
|
`type=docker,name=${appName}`,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add secrets properly formatted
|
||||||
|
const exportEnvs = [];
|
||||||
|
for (const envVar of envVariables) {
|
||||||
|
const [key, value] = envVar.split("=");
|
||||||
|
if (key && value) {
|
||||||
|
buildArgs.push("--secret", `id=${key},env=${key}`);
|
||||||
|
exportEnvs.push(`export ${key}=${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildArgs.push(buildAppDirectory);
|
||||||
|
|
||||||
const bashCommand = `
|
const bashCommand = `
|
||||||
echo "Building with Railpack..." >> "${logPath}";
|
# Ensure we have a builder with containerd
|
||||||
docker container inspect buildkit >/dev/null 2>&1 || docker run --rm --privileged -d --name buildkit moby/buildkit;
|
docker buildx create --use --name builder-containerd --driver docker-container || true
|
||||||
export BUILDKIT_HOST=docker-container://buildkit;
|
docker buildx use builder-containerd
|
||||||
${command} >> ${logPath} 2>> ${logPath} || {
|
|
||||||
echo "❌ Railpack build failed" >> ${logPath};
|
echo "Preparing Railpack build plan..." >> "${logPath}";
|
||||||
exit 1;
|
railpack ${prepareArgs.join(" ")} >> ${logPath} 2>> ${logPath} || {
|
||||||
}
|
echo "❌ Railpack prepare failed" >> ${logPath};
|
||||||
echo "✅ Railpack build completed." >> ${logPath};
|
exit 1;
|
||||||
`;
|
}
|
||||||
|
echo "✅ Railpack prepare completed." >> ${logPath};
|
||||||
|
|
||||||
|
echo "Building with Railpack frontend..." >> "${logPath}";
|
||||||
|
# Export environment variables for secrets
|
||||||
|
${exportEnvs.join("\n")}
|
||||||
|
docker ${buildArgs.join(" ")} >> ${logPath} 2>> ${logPath} || {
|
||||||
|
echo "❌ Railpack build failed" >> ${logPath};
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
echo "✅ Railpack build completed." >> ${logPath};
|
||||||
|
`;
|
||||||
|
|
||||||
return bashCommand;
|
return bashCommand;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user