mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-06 06:25:28 +02:00
Reapply "Merge branch 'canary' into kucherenko/canary"
This reverts commit e6cb6454db.
This commit is contained in:
46
packages/server/src/utils/docker/collision.ts
Normal file
46
packages/server/src/utils/docker/collision.ts
Normal 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;
|
||||
};
|
||||
62
packages/server/src/utils/docker/collision/root-network.ts
Normal file
62
packages/server/src/utils/docker/collision/root-network.ts
Normal 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;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user