From b814bdc612299643a392e59440e903c5e6e6f1ec Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:13:39 -0600 Subject: [PATCH] Refactor application and compose deployment logic: remove unused buildApplication function, streamline command logging for deployment, and enhance static command generation for improved maintainability and clarity in the codebase. --- packages/server/src/services/application.ts | 3 - packages/server/src/services/compose.ts | 18 +++++- packages/server/src/utils/builders/index.ts | 45 +------------- packages/server/src/utils/builders/static.ts | 20 ++++++- packages/server/src/utils/cluster/upload.ts | 63 +------------------- packages/server/src/utils/docker/domain.ts | 3 +- 6 files changed, 38 insertions(+), 114 deletions(-) diff --git a/packages/server/src/services/application.ts b/packages/server/src/services/application.ts index 181467a76..8dc67ddb6 100644 --- a/packages/server/src/services/application.ts +++ b/packages/server/src/services/application.ts @@ -7,7 +7,6 @@ import { } from "@dokploy/server/db/schema"; import { getAdvancedStats } from "@dokploy/server/monitoring/utils"; import { - buildApplication, getBuildCommand, mechanizeDockerContainer, } from "@dokploy/server/utils/builders"; @@ -187,8 +186,6 @@ export const deployApplication = async ({ command += await cloneBitbucketRepository(application); } else if (application.sourceType === "git") { command += await cloneGitRepository(application); - } else if (application.sourceType === "drop") { - await buildApplication(application, deployment.logPath); } else if (application.sourceType === "docker") { command += await buildRemoteDocker(application); } diff --git a/packages/server/src/services/compose.ts b/packages/server/src/services/compose.ts index 4b96f443d..2e2a2fc59 100644 --- a/packages/server/src/services/compose.ts +++ b/packages/server/src/services/compose.ts @@ -232,8 +232,15 @@ export const deployCompose = async ({ command += getCreateComposeFileCommand(entity); } + let commandWithLog = `(${command}) >> ${deployment.logPath} 2>&1`; + if (compose.serverId) { + await execAsyncRemote(compose.serverId, commandWithLog); + } else { + await execAsync(commandWithLog); + } + command += await getBuildComposeCommand(entity); - const commandWithLog = `(${command}) >> ${deployment.logPath} 2>&1`; + commandWithLog = `(${command}) >> ${deployment.logPath} 2>&1`; if (compose.serverId) { await execAsyncRemote(compose.serverId, commandWithLog); } else { @@ -293,8 +300,15 @@ export const rebuildCompose = async ({ if (compose.sourceType === "raw") { command += getCreateComposeFileCommand(compose); } + + let commandWithLog = `(${command}) >> ${deployment.logPath} 2>&1`; + if (compose.serverId) { + await execAsyncRemote(compose.serverId, commandWithLog); + } else { + await execAsync(commandWithLog); + } command += await getBuildComposeCommand(compose); - const commandWithLog = `(${command}) >> ${deployment.logPath} 2>&1`; + commandWithLog = `(${command}) >> ${deployment.logPath} 2>&1`; if (compose.serverId) { await execAsyncRemote(compose.serverId, commandWithLog); } else { diff --git a/packages/server/src/utils/builders/index.ts b/packages/server/src/utils/builders/index.ts index 207238ca5..bfc3e894a 100644 --- a/packages/server/src/utils/builders/index.ts +++ b/packages/server/src/utils/builders/index.ts @@ -1,7 +1,6 @@ -import { createWriteStream } from "node:fs"; import type { InferResultType } from "@dokploy/server/types/with"; import type { CreateServiceOptions } from "dockerode"; -import { uploadImage, uploadImageRemoteCommand } from "../cluster/upload"; +import { uploadImageRemoteCommand } from "../cluster/upload"; import { calculateResources, generateBindMounts, @@ -34,48 +33,6 @@ export type ApplicationNested = InferResultType< } >; -export const buildApplication = async ( - application: ApplicationNested, - logPath: string, -) => { - const writeStream = createWriteStream(logPath, { flags: "a" }); - const { buildType, sourceType } = application; - try { - writeStream.write( - `\nBuild ${buildType}: ✅\nSource Type: ${sourceType}: ✅\n`, - ); - console.log(`Build ${buildType}: ✅`); - // if (buildType === "nixpacks") { - // await buildNixpacks(application, writeStream); - // } else if (buildType === "heroku_buildpacks") { - // await buildHeroku(application, writeStream); - // } else if (buildType === "paketo_buildpacks") { - // await buildPaketo(application, writeStream); - // } else if (buildType === "dockerfile") { - // await buildCustomDocker(application, writeStream); - // } else if (buildType === "static") { - // await buildStatic(application, writeStream); - // } else if (buildType === "railpack") { - // await buildRailpack(application, writeStream); - // } - - if (application.registryId) { - await uploadImage(application, writeStream); - } - await mechanizeDockerContainer(application); - writeStream.write("Docker Deployed: ✅"); - } catch (error) { - if (error instanceof Error) { - writeStream.write(`Error ❌\n${error?.message}`); - } else { - writeStream.write("Error ❌"); - } - throw error; - } finally { - writeStream.end(); - } -}; - export const getBuildCommand = (application: ApplicationNested) => { let command = ""; const { buildType, registry } = application; diff --git a/packages/server/src/utils/builders/static.ts b/packages/server/src/utils/builders/static.ts index 4ddb290be..99fa25285 100644 --- a/packages/server/src/utils/builders/static.ts +++ b/packages/server/src/utils/builders/static.ts @@ -29,16 +29,32 @@ http { `; export const getStaticCommand = (application: ApplicationNested) => { - const { publishDirectory } = application; + const { publishDirectory, isStaticSpa } = application; const buildAppDirectory = getBuildAppDirectory(application); + let command = ""; + if (isStaticSpa) { + command += getCreateFileCommand( + buildAppDirectory, + "nginx.conf", + nginxSpaConfig, + ); + } - let command = getCreateFileCommand( + command += getCreateFileCommand( + buildAppDirectory, + ".dockerignore", + [".git", ".env", "Dockerfile", ".dockerignore"].join("\n"), + ); + + command += getCreateFileCommand( buildAppDirectory, "Dockerfile", [ "FROM nginx:alpine", "WORKDIR /usr/share/nginx/html/", + isStaticSpa ? "COPY nginx.conf /etc/nginx/nginx.conf" : "", `COPY ${publishDirectory || "."} .`, + 'CMD ["nginx", "-g", "daemon off;"]', ].join("\n"), ); diff --git a/packages/server/src/utils/cluster/upload.ts b/packages/server/src/utils/cluster/upload.ts index 6a2dfd66f..33be287e1 100644 --- a/packages/server/src/utils/cluster/upload.ts +++ b/packages/server/src/utils/cluster/upload.ts @@ -1,63 +1,4 @@ -import type { WriteStream } from "node:fs"; import type { ApplicationNested } from "../builders"; -import { spawnAsync } from "../process/spawnAsync"; - -export const uploadImage = async ( - application: ApplicationNested, - writeStream: WriteStream, -) => { - const registry = application.registry; - - if (!registry) { - throw new Error("Registry not found"); - } - - const { registryUrl, imagePrefix, username } = registry; - const { appName } = application; - const imageName = `${appName}:latest`; - - const finalURL = registryUrl; - - // Build registry tag in correct format: registry.com/owner/image:tag - // For ghcr.io: ghcr.io/username/image:tag - // For docker.io: docker.io/username/image:tag - const registryTag = imagePrefix - ? `${registryUrl ? `${registryUrl}/` : ""}${imagePrefix}/${imageName}` - : `${registryUrl ? `${registryUrl}/` : ""}${username}/${imageName}`; - - try { - writeStream.write( - `📦 [Enabled Registry] Uploading image to ${registry.registryType} | ${imageName} | ${finalURL} | ${registryTag}\n`, - ); - const loginCommand = spawnAsync( - "docker", - ["login", finalURL, "-u", registry.username, "--password-stdin"], - (data) => { - if (writeStream.writable) { - writeStream.write(data); - } - }, - ); - loginCommand.child?.stdin?.write(registry.password); - loginCommand.child?.stdin?.end(); - await loginCommand; - - await spawnAsync("docker", ["tag", imageName, registryTag], (data) => { - if (writeStream.writable) { - writeStream.write(data); - } - }); - - await spawnAsync("docker", ["push", registryTag], (data) => { - if (writeStream.writable) { - writeStream.write(data); - } - }); - } catch (error) { - console.log(error); - throw error; - } -}; export const uploadImageRemoteCommand = (application: ApplicationNested) => { const registry = application.registry; @@ -74,8 +15,8 @@ export const uploadImageRemoteCommand = (application: ApplicationNested) => { // Build registry tag in correct format: registry.com/owner/image:tag const registryTag = imagePrefix - ? `${registryUrl}/${imagePrefix}/${imageName}` - : `${registryUrl}/${username}/${imageName}`; + ? `${registryUrl ? `${registryUrl}/` : ""}${imagePrefix}/${imageName}` + : `${registryUrl ? `${registryUrl}/` : ""}${username}/${imageName}`; try { const command = ` diff --git a/packages/server/src/utils/docker/domain.ts b/packages/server/src/utils/docker/domain.ts index 3d4167d2e..ffe900302 100644 --- a/packages/server/src/utils/docker/domain.ts +++ b/packages/server/src/utils/docker/domain.ts @@ -132,7 +132,6 @@ exit 1; `; } }; -// (node:59875) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 SIGTERM listeners added to [process]. Use emitter.setMaxListeners() to increase limit export const addDomainToCompose = async ( compose: Compose, domains: Domain[], @@ -142,7 +141,7 @@ export const addDomainToCompose = async ( let result: ComposeSpecification | null; if (compose.serverId) { - result = await loadDockerComposeRemote(compose); // aca hay que ir al servidor e ir a traer el compose file al servidor + result = await loadDockerComposeRemote(compose); } else { result = await loadDockerCompose(compose); }