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.

This commit is contained in:
Mauricio Siu
2025-11-09 11:13:39 -06:00
parent d8ab7a59ff
commit b814bdc612
6 changed files with 38 additions and 114 deletions

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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"),
);

View File

@@ -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 = `

View File

@@ -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);
}