Reapply "Merge branch 'canary' into kucherenko/canary"

This reverts commit e6cb6454db.
This commit is contained in:
Mauricio Siu
2025-03-02 00:30:02 -06:00
parent e6cb6454db
commit 747c2137c9
639 changed files with 82888 additions and 17188 deletions

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,
@@ -108,7 +109,7 @@ export const loadDockerComposeRemote = async (
if (!stdout) return null;
const parsedConfig = load(stdout) as ComposeSpecification;
return parsedConfig;
} catch (err) {
} catch (_err) {
return null;
}
};
@@ -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;
}
@@ -203,9 +210,6 @@ export const addDomainToCompose = async (
if (!result?.services?.[serviceName]) {
throw new Error(`The service ${serviceName} not found in the compose`);
}
if (!result.services[serviceName].labels) {
result.services[serviceName].labels = [];
}
const httpLabels = await createDomainLabels(appName, domain, "web");
if (https) {
@@ -217,7 +221,24 @@ export const addDomainToCompose = async (
httpLabels.push(...httpsLabels);
}
const labels = result.services[serviceName].labels;
let labels: DefinitionsService["labels"] = [];
if (compose.composeType === "docker-compose") {
if (!result.services[serviceName].labels) {
result.services[serviceName].labels = [];
}
labels = result.services[serviceName].labels;
} else {
// Stack Case
if (!result.services[serviceName].deploy) {
result.services[serviceName].deploy = {};
}
if (!result.services[serviceName].deploy.labels) {
result.services[serviceName].deploy.labels = [];
}
labels = result.services[serviceName].deploy.labels;
}
if (Array.isArray(labels)) {
if (!labels.includes("traefik.enable=true")) {
@@ -226,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;
};

View File

@@ -100,7 +100,7 @@ export const containerExists = async (containerName: string) => {
try {
await container.inspect();
return true;
} catch (error) {
} catch (_error) {
return false;
}
};
@@ -144,10 +144,11 @@ export const getContainerByName = (name: string): Promise<ContainerInfo> => {
};
export const cleanUpUnusedImages = async (serverId?: string) => {
try {
const command = "docker image prune --force";
if (serverId) {
await execAsyncRemote(serverId, "docker image prune --all --force");
await execAsyncRemote(serverId, command);
} else {
await execAsync("docker image prune --all --force");
await execAsync(command);
}
} catch (error) {
console.error(error);
@@ -157,10 +158,11 @@ export const cleanUpUnusedImages = async (serverId?: string) => {
export const cleanStoppedContainers = async (serverId?: string) => {
try {
const command = "docker container prune --force";
if (serverId) {
await execAsyncRemote(serverId, "docker container prune --force");
await execAsyncRemote(serverId, command);
} else {
await execAsync("docker container prune --force");
await execAsync(command);
}
} catch (error) {
console.error(error);
@@ -170,10 +172,11 @@ export const cleanStoppedContainers = async (serverId?: string) => {
export const cleanUpUnusedVolumes = async (serverId?: string) => {
try {
const command = "docker volume prune --force";
if (serverId) {
await execAsyncRemote(serverId, "docker volume prune --all --force");
await execAsyncRemote(serverId, command);
} else {
await execAsync("docker volume prune --all --force");
await execAsync(command);
}
} catch (error) {
console.error(error);
@@ -199,21 +202,20 @@ export const cleanUpInactiveContainers = async () => {
};
export const cleanUpDockerBuilder = async (serverId?: string) => {
const command = "docker builder prune --all --force";
if (serverId) {
await execAsyncRemote(serverId, "docker builder prune --all --force");
await execAsyncRemote(serverId, command);
} else {
await execAsync("docker builder prune --all --force");
await execAsync(command);
}
};
export const cleanUpSystemPrune = async (serverId?: string) => {
const command = "docker system prune --all --force --volumes";
if (serverId) {
await execAsyncRemote(
serverId,
"docker system prune --all --force --volumes",
);
await execAsyncRemote(serverId, command);
} else {
await execAsync("docker system prune --all --force --volumes");
await execAsync(command);
}
};
@@ -238,7 +240,7 @@ export const startServiceRemote = async (serverId: string, appName: string) => {
export const removeService = async (
appName: string,
serverId?: string | null,
deleteVolumes = false,
_deleteVolumes = false,
) => {
try {
const command = `docker service rm ${appName}`;
@@ -276,12 +278,15 @@ export const prepareEnvironmentVariables = (
return resolvedVars;
};
export const prepareBuildArgs = (input: string | null) => {
const pairs = (input ?? "").split("\n");
export const getEnviromentVariablesObject = (
input: string | null,
projectEnv?: string | null,
) => {
const envs = prepareEnvironmentVariables(input, projectEnv);
const jsonObject: Record<string, string> = {};
for (const pair of pairs) {
for (const pair of envs) {
const [key, value] = pair.split("=");
if (key && value) {
jsonObject[key] = value;