From 005f73d6658f3e0a0c922d793784571649f60ed4 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 15 Mar 2025 17:11:20 -0600 Subject: [PATCH 1/4] refactor: enhance Railpack build process by introducing preparation step and environment variable handling --- .../server/src/utils/builders/railpack.ts | 126 +++++++++++++----- 1 file changed, 96 insertions(+), 30 deletions(-) diff --git a/packages/server/src/utils/builders/railpack.ts b/packages/server/src/utils/builders/railpack.ts index ae55a638c..e99918861 100644 --- a/packages/server/src/utils/builders/railpack.ts +++ b/packages/server/src/utils/builders/railpack.ts @@ -3,7 +3,6 @@ import type { ApplicationNested } from "."; import { prepareEnvironmentVariables } from "../docker/utils"; import { getBuildAppDirectory } from "../filesystem/directory"; import { spawnAsync } from "../process/spawnAsync"; -import { execAsync } from "../process/execAsync"; export const buildRailpack = async ( application: ApplicationNested, @@ -17,32 +16,62 @@ export const buildRailpack = async ( ); try { - // Ensure buildkit container is running, create if it doesn't exist - await execAsync( - "docker container inspect buildkit >/dev/null 2>&1 || docker run --rm --privileged -d --name buildkit moby/buildkit", - ); + // First prepare the build plan and info + const prepareArgs = [ + "prepare", + buildAppDirectory, + "--plan-out", + `${buildAppDirectory}/railpack-plan.json`, + "--info-out", + `${buildAppDirectory}/railpack-info.json`, + ]; - // Build the application using railpack - const args = ["build", buildAppDirectory, "--name", appName]; - - // Add environment variables + // Add environment variables to prepare command 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( - "railpack", - args, + "docker", + buildArgs, (data) => { if (writeStream.writable) { writeStream.write(data); } }, { - env: { - ...process.env, - BUILDKIT_HOST: "docker-container://buildkit", - }, + env: { ...process.env, ...env }, }, ); @@ -63,25 +92,62 @@ export const getRailpackCommand = ( application.project.env, ); - // Build the application using railpack - const args = ["build", buildAppDirectory, "--name", appName]; + // Prepare command + const prepareArgs = [ + "prepare", + buildAppDirectory, + "--plan-out", + `${buildAppDirectory}/railpack-plan.json`, + "--info-out", + `${buildAppDirectory}/railpack-info.json`, + ]; - // Add environment variables 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 = ` - echo "Building with Railpack..." >> "${logPath}"; - docker container inspect buildkit >/dev/null 2>&1 || docker run --rm --privileged -d --name buildkit moby/buildkit; - export BUILDKIT_HOST=docker-container://buildkit; - ${command} >> ${logPath} 2>> ${logPath} || { - echo "❌ Railpack build failed" >> ${logPath}; - exit 1; - } - echo "✅ Railpack build completed." >> ${logPath}; - `; +echo "Preparing Railpack build plan..." >> "${logPath}"; +railpack ${prepareArgs.join(" ")} >> ${logPath} 2>> ${logPath} || { + echo "❌ Railpack prepare failed" >> ${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; }; +// docker buildx build --build-arg BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v0.0.55 -f /Users/mauricio/Documents/Github/Personal/dokploy/apps/dokploy/.docker/applications/dsfgsdfg-sdfgdsfg-fyk3r9/code/astro/railpack-plan.json /Users/mauricio/Documents/Github/Personal/dokploy/apps/dokploy/.docker/applications/dsfgsdfg-sdfgdsfg-fyk3r9/code/astro From 31164c979804d7125c0fa303de3cdc515688a4b7 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 15 Mar 2025 20:42:53 -0600 Subject: [PATCH 2/4] chore: remove console log statements from WebSocket connection handling and ensure builder container for Railpack is created --- apps/dokploy/server/wss/listen-deployment.ts | 2 -- packages/server/src/utils/builders/railpack.ts | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/dokploy/server/wss/listen-deployment.ts b/apps/dokploy/server/wss/listen-deployment.ts index 4a25c6f0e..581c04d7b 100644 --- a/apps/dokploy/server/wss/listen-deployment.ts +++ b/apps/dokploy/server/wss/listen-deployment.ts @@ -61,7 +61,6 @@ export const setupDeploymentLogsWebSocketServer = ( } stream .on("close", () => { - console.log("Connection closed ✅"); client.end(); ws.close(); }) @@ -86,7 +85,6 @@ export const setupDeploymentLogsWebSocketServer = ( }); ws.on("close", () => { - console.log("Connection closed ✅, From WS"); client.end(); }); } else { diff --git a/packages/server/src/utils/builders/railpack.ts b/packages/server/src/utils/builders/railpack.ts index e99918861..bc23338d4 100644 --- a/packages/server/src/utils/builders/railpack.ts +++ b/packages/server/src/utils/builders/railpack.ts @@ -131,6 +131,10 @@ export const getRailpackCommand = ( buildArgs.push(buildAppDirectory); const bashCommand = ` +# Ensure we have a builder with containerd +docker buildx create --use --name builder-containerd --driver docker-container || true +docker buildx use builder-containerd + echo "Preparing Railpack build plan..." >> "${logPath}"; railpack ${prepareArgs.join(" ")} >> ${logPath} 2>> ${logPath} || { echo "❌ Railpack prepare failed" >> ${logPath}; From 8d9d00d0c6f65a11f7599ec9423f94b62211e8d4 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 15 Mar 2025 20:43:22 -0600 Subject: [PATCH 3/4] refactor: streamline container parsing logic in Docker service functions --- packages/server/src/services/docker.ts | 160 ++++++++++++------------- 1 file changed, 76 insertions(+), 84 deletions(-) diff --git a/packages/server/src/services/docker.ts b/packages/server/src/services/docker.ts index 69ae446a9..bb70d28fe 100644 --- a/packages/server/src/services/docker.ts +++ b/packages/server/src/services/docker.ts @@ -136,26 +136,24 @@ export const getContainersByAppNameMatch = async ( result = stdout.trim().split("\n"); } - const containers = result - .map((line) => { - const parts = line.split(" | "); - const containerId = parts[0] - ? parts[0].replace("CONTAINER ID : ", "").trim() - : "No container id"; - const name = parts[1] - ? parts[1].replace("Name: ", "").trim() - : "No container name"; + const containers = result.map((line) => { + const parts = line.split(" | "); + const containerId = parts[0] + ? parts[0].replace("CONTAINER ID : ", "").trim() + : "No container id"; + const name = parts[1] + ? parts[1].replace("Name: ", "").trim() + : "No container name"; - const state = parts[2] - ? parts[2].replace("State: ", "").trim() - : "No state"; - return { - containerId, - name, - state, - }; - }) - .sort((a, b) => a.name.localeCompare(b.name)); + const state = parts[2] + ? parts[2].replace("State: ", "").trim() + : "No state"; + return { + containerId, + name, + state, + }; + }); return containers || []; } catch (_error) {} @@ -192,30 +190,28 @@ export const getStackContainersByAppName = async ( result = stdout.trim().split("\n"); } - const containers = result - .map((line) => { - const parts = line.split(" | "); - const containerId = parts[0] - ? parts[0].replace("CONTAINER ID : ", "").trim() - : "No container id"; - const name = parts[1] - ? parts[1].replace("Name: ", "").trim() - : "No container name"; + const containers = result.map((line) => { + const parts = line.split(" | "); + const containerId = parts[0] + ? parts[0].replace("CONTAINER ID : ", "").trim() + : "No container id"; + const name = parts[1] + ? parts[1].replace("Name: ", "").trim() + : "No container name"; - const state = parts[2] - ? parts[2].replace("State: ", "").trim().toLowerCase() - : "No state"; - const node = parts[3] - ? parts[3].replace("Node: ", "").trim() - : "No specific node"; - return { - containerId, - name, - state, - node, - }; - }) - .sort((a, b) => a.name.localeCompare(b.name)); + const state = parts[2] + ? parts[2].replace("State: ", "").trim().toLowerCase() + : "No state"; + const node = parts[3] + ? parts[3].replace("Node: ", "").trim() + : "No specific node"; + return { + containerId, + name, + state, + node, + }; + }); return containers || []; } catch (_error) {} @@ -253,31 +249,29 @@ export const getServiceContainersByAppName = async ( result = stdout.trim().split("\n"); } - const containers = result - .map((line) => { - const parts = line.split(" | "); - const containerId = parts[0] - ? parts[0].replace("CONTAINER ID : ", "").trim() - : "No container id"; - const name = parts[1] - ? parts[1].replace("Name: ", "").trim() - : "No container name"; + const containers = result.map((line) => { + const parts = line.split(" | "); + const containerId = parts[0] + ? parts[0].replace("CONTAINER ID : ", "").trim() + : "No container id"; + const name = parts[1] + ? parts[1].replace("Name: ", "").trim() + : "No container name"; - const state = parts[2] - ? parts[2].replace("State: ", "").trim().toLowerCase() - : "No state"; + const state = parts[2] + ? parts[2].replace("State: ", "").trim().toLowerCase() + : "No state"; - const node = parts[3] - ? parts[3].replace("Node: ", "").trim() - : "No specific node"; - return { - containerId, - name, - state, - node, - }; - }) - .sort((a, b) => a.name.localeCompare(b.name)); + const node = parts[3] + ? parts[3].replace("Node: ", "").trim() + : "No specific node"; + return { + containerId, + name, + state, + node, + }; + }); return containers || []; } catch (_error) {} @@ -318,25 +312,23 @@ export const getContainersByAppLabel = async ( const lines = stdout.trim().split("\n"); - const containers = lines - .map((line) => { - const parts = line.split(" | "); - const containerId = parts[0] - ? parts[0].replace("CONTAINER ID : ", "").trim() - : "No container id"; - const name = parts[1] - ? parts[1].replace("Name: ", "").trim() - : "No container name"; - const state = parts[2] - ? parts[2].replace("State: ", "").trim() - : "No state"; - return { - containerId, - name, - state, - }; - }) - .sort((a, b) => a.name.localeCompare(b.name)); + const containers = lines.map((line) => { + const parts = line.split(" | "); + const containerId = parts[0] + ? parts[0].replace("CONTAINER ID : ", "").trim() + : "No container id"; + const name = parts[1] + ? parts[1].replace("Name: ", "").trim() + : "No container name"; + const state = parts[2] + ? parts[2].replace("State: ", "").trim() + : "No state"; + return { + containerId, + name, + state, + }; + }); return containers || []; } catch (_error) {} From be64a1554d08ad7630d7c387245cd366c3f9f492 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 15 Mar 2025 20:45:38 -0600 Subject: [PATCH 4/4] chore: remove commented-out Docker build command from Railpack builder utility --- packages/server/src/utils/builders/railpack.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/server/src/utils/builders/railpack.ts b/packages/server/src/utils/builders/railpack.ts index bc23338d4..bd2241c62 100644 --- a/packages/server/src/utils/builders/railpack.ts +++ b/packages/server/src/utils/builders/railpack.ts @@ -154,4 +154,3 @@ echo "✅ Railpack build completed." >> ${logPath}; return bashCommand; }; -// docker buildx build --build-arg BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v0.0.55 -f /Users/mauricio/Documents/Github/Personal/dokploy/apps/dokploy/.docker/applications/dsfgsdfg-sdfgdsfg-fyk3r9/code/astro/railpack-plan.json /Users/mauricio/Documents/Github/Personal/dokploy/apps/dokploy/.docker/applications/dsfgsdfg-sdfgdsfg-fyk3r9/code/astro