Merge pull request #1300 from Dokploy/canary

🚀 Release v0.18.3
This commit is contained in:
Mauricio Siu
2025-02-10 00:35:31 -06:00
committed by GitHub
86 changed files with 10315 additions and 515 deletions

View File

@@ -69,6 +69,7 @@ export const compose = pgTable("compose", {
composePath: text("composePath").notNull().default("./docker-compose.yml"),
suffix: text("suffix").notNull().default(""),
randomize: boolean("randomize").notNull().default(false),
isolatedDeployment: boolean("isolatedDeployment").notNull().default(false),
composeStatus: applicationStatus("composeStatus").notNull().default("idle"),
projectId: text("projectId")
.notNull()

View File

@@ -73,6 +73,7 @@ export * from "./utils/builders/utils";
export * from "./utils/cluster/upload";
export * from "./utils/docker/compose";
export * from "./utils/docker/collision";
export * from "./utils/docker/domain";
export * from "./utils/docker/utils";
export * from "./utils/docker/types";

View File

@@ -34,6 +34,12 @@ export const buildCompose = async (compose: ComposeNested, logPath: string) => {
await writeDomainsToCompose(compose, domains);
createEnvFile(compose);
if (compose.isolatedDeployment) {
await execAsync(
`docker network inspect ${compose.appName} >/dev/null 2>&1 || docker network create --attachable ${compose.appName}`,
);
}
const logContent = `
App Name: ${appName}
Build Compose 🐳
@@ -73,6 +79,12 @@ export const buildCompose = async (compose: ComposeNested, logPath: string) => {
},
);
if (compose.isolatedDeployment) {
await execAsync(
`docker network connect ${compose.appName} $(docker ps --filter "name=dokploy-traefik" -q) >/dev/null 2>&1`,
).catch(() => {});
}
writeStream.write("Docker Compose Deployed: ✅");
} catch (error) {
writeStream.write(`Error ❌ ${(error as Error).message}`);
@@ -128,9 +140,10 @@ Compose Type: ${composeType} ✅`;
cd "${projectPath}";
${exportEnvCommand}
${exportEnvCommand}
${compose.isolatedDeployment ? `docker network inspect ${compose.appName} >/dev/null 2>&1 || docker network create --attachable ${compose.appName}` : ""}
docker ${command.split(" ").join(" ")} >> "${logPath}" 2>&1 || { echo "Error: ❌ Docker command failed" >> "${logPath}"; exit 1; }
${compose.isolatedDeployment ? `docker network connect ${compose.appName} $(docker ps --filter "name=dokploy-traefik" -q) >/dev/null 2>&1` : ""}
echo "Docker Compose Deployed: ✅" >> "${logPath}"
} || {

View File

@@ -0,0 +1,46 @@
import { findComposeById } from "@dokploy/server/services/compose";
import { dump, load } from "js-yaml";
import { addAppNameToAllServiceNames } from "./collision/root-network";
import { generateRandomHash } from "./compose";
import { addSuffixToAllVolumes } from "./compose/volume";
import type { ComposeSpecification } from "./types";
export const addAppNameToPreventCollision = (
composeData: ComposeSpecification,
appName: string,
): ComposeSpecification => {
let updatedComposeData = { ...composeData };
updatedComposeData = addAppNameToAllServiceNames(updatedComposeData, appName);
updatedComposeData = addSuffixToAllVolumes(updatedComposeData, appName);
return updatedComposeData;
};
export const randomizeIsolatedDeploymentComposeFile = async (
composeId: string,
suffix?: string,
) => {
const compose = await findComposeById(composeId);
const composeFile = compose.composeFile;
const composeData = load(composeFile) as ComposeSpecification;
const randomSuffix = suffix || compose.appName || generateRandomHash();
const newComposeFile = addAppNameToPreventCollision(
composeData,
randomSuffix,
);
return dump(newComposeFile);
};
export const randomizeDeployableSpecificationFile = (
composeSpec: ComposeSpecification,
suffix?: string,
) => {
if (!suffix) {
return composeSpec;
}
const newComposeFile = addAppNameToPreventCollision(composeSpec, suffix);
return newComposeFile;
};

View File

@@ -0,0 +1,62 @@
import _ from "lodash";
import type { ComposeSpecification, DefinitionsService } from "../types";
export const addAppNameToRootNetwork = (
composeData: ComposeSpecification,
appName: string,
): ComposeSpecification => {
const updatedComposeData = { ...composeData };
// Initialize networks if it doesn't exist
if (!updatedComposeData.networks) {
updatedComposeData.networks = {};
}
// Add the new network with the app name
updatedComposeData.networks[appName] = {
name: appName,
external: true,
};
return updatedComposeData;
};
export const addAppNameToServiceNetworks = (
services: { [key: string]: DefinitionsService },
appName: string,
): { [key: string]: DefinitionsService } => {
return _.mapValues(services, (service) => {
if (!service.networks) {
service.networks = [appName];
return service;
}
if (Array.isArray(service.networks)) {
if (!service.networks.includes(appName)) {
service.networks.push(appName);
}
} else {
service.networks[appName] = {};
}
return service;
});
};
export const addAppNameToAllServiceNames = (
composeData: ComposeSpecification,
appName: string,
): ComposeSpecification => {
let updatedComposeData = { ...composeData };
updatedComposeData = addAppNameToRootNetwork(updatedComposeData, appName);
if (updatedComposeData.services) {
updatedComposeData.services = addAppNameToServiceNetworks(
updatedComposeData.services,
appName,
);
}
return updatedComposeData;
};

View File

@@ -26,6 +26,7 @@ import {
createComposeFileRaw,
createComposeFileRawRemote,
} from "../providers/raw";
import { randomizeDeployableSpecificationFile } from "./collision";
import { randomizeSpecificationFile } from "./compose";
import type {
ComposeSpecification,
@@ -190,7 +191,13 @@ export const addDomainToCompose = async (
return null;
}
if (compose.randomize) {
if (compose.isolatedDeployment) {
const randomized = randomizeDeployableSpecificationFile(
result,
compose.suffix || compose.appName,
);
result = randomized;
} else if (compose.randomize) {
const randomized = randomizeSpecificationFile(result, compose.suffix);
result = randomized;
}
@@ -240,14 +247,18 @@ export const addDomainToCompose = async (
labels.push(...httpLabels);
}
// Add the dokploy-network to the service
result.services[serviceName].networks = addDokployNetworkToService(
result.services[serviceName].networks,
);
if (!compose.isolatedDeployment) {
// Add the dokploy-network to the service
result.services[serviceName].networks = addDokployNetworkToService(
result.services[serviceName].networks,
);
}
}
// Add dokploy-network to the root of the compose file
result.networks = addDokployNetworkToRoot(result.networks);
if (!compose.isolatedDeployment) {
result.networks = addDokployNetworkToRoot(result.networks);
}
return result;
};