mirror of
https://github.com/andwati/dokploy.git
synced 2026-10-26 06:52:17 +00:00
feat(networks): enhance network management and UI components
- Added functionality for assigning Docker networks to services, allowing users to manage network associations directly from the UI. - Introduced new components for assigning networks to both individual services and compose files, improving user experience and flexibility. - Updated existing components to integrate network assignment features, ensuring seamless interaction within the dashboard. - Enhanced the database schema to support new network-related fields, including `networkIds` and `detachDokployNetwork`, for better service configuration. - Improved the layout and responsiveness of various UI elements to accommodate new features and enhance usability.
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import fs, { existsSync, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { network } from "@dokploy/server/db/schema";
|
||||
import type { Compose } from "@dokploy/server/services/compose";
|
||||
import type { Domain } from "@dokploy/server/services/domain";
|
||||
import { inArray } from "drizzle-orm";
|
||||
import { parse, stringify } from "yaml";
|
||||
import { execAsyncRemote } from "../process/execAsync";
|
||||
import { cloneBitbucketRepository } from "../providers/bitbucket";
|
||||
@@ -228,14 +231,79 @@ export const addDomainToCompose = async (
|
||||
}
|
||||
}
|
||||
|
||||
// Add dokploy-network to the root of the compose file
|
||||
const injectedNetworkNames = await applyServiceNetworks(result, compose);
|
||||
|
||||
if (!compose.isolatedDeployment) {
|
||||
result.networks = addDokployNetworkToRoot(result.networks);
|
||||
declareUsedNetworksInRoot(result, injectedNetworkNames);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const applyServiceNetworks = async (
|
||||
result: ComposeSpecification,
|
||||
compose: Compose,
|
||||
) => {
|
||||
const injectedNetworkNames = new Set<string>();
|
||||
const serviceNetworks = compose.serviceNetworks ?? [];
|
||||
if (serviceNetworks.length === 0) return injectedNetworkNames;
|
||||
|
||||
const allNetworkIds = [
|
||||
...new Set(serviceNetworks.flatMap((s) => s.networkIds)),
|
||||
];
|
||||
const networks =
|
||||
allNetworkIds.length > 0
|
||||
? await db.query.network.findMany({
|
||||
where: inArray(network.networkId, allNetworkIds),
|
||||
})
|
||||
: [];
|
||||
|
||||
for (const config of serviceNetworks) {
|
||||
const service = result.services?.[config.serviceName];
|
||||
if (!service) continue;
|
||||
|
||||
for (const networkId of config.networkIds) {
|
||||
const match = networks.find((n) => n.networkId === networkId);
|
||||
if (!match) continue;
|
||||
service.networks = addDokployNetworkToService(
|
||||
service.networks,
|
||||
match.name,
|
||||
);
|
||||
injectedNetworkNames.add(match.name);
|
||||
}
|
||||
|
||||
if (config.detachDokployNetwork) {
|
||||
removeNetworkFromService(service, "dokploy-network");
|
||||
removeNetworkFromService(service, "default");
|
||||
removeDokployNetworkLabel(service);
|
||||
}
|
||||
}
|
||||
|
||||
return injectedNetworkNames;
|
||||
};
|
||||
|
||||
const declareUsedNetworksInRoot = (
|
||||
result: ComposeSpecification,
|
||||
injectedNetworkNames: Set<string>,
|
||||
) => {
|
||||
const isUsed = (name: string) =>
|
||||
Object.values(result.services ?? {}).some((service) => {
|
||||
const nets = service?.networks;
|
||||
if (Array.isArray(nets)) return nets.includes(name);
|
||||
if (nets && typeof nets === "object") return name in nets;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (isUsed("dokploy-network")) {
|
||||
result.networks = addDokployNetworkToRoot(result.networks);
|
||||
}
|
||||
for (const name of injectedNetworkNames) {
|
||||
if (isUsed(name)) {
|
||||
result.networks = addDokployNetworkToRoot(result.networks, name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const writeComposeFile = async (
|
||||
compose: Compose,
|
||||
composeSpec: ComposeSpecification,
|
||||
@@ -349,9 +417,10 @@ export const createDomainLabels = (
|
||||
|
||||
export const addDokployNetworkToService = (
|
||||
networkService: DefinitionsService["networks"],
|
||||
networkName = "dokploy-network",
|
||||
) => {
|
||||
let networks = networkService;
|
||||
const network = "dokploy-network";
|
||||
const network = networkName;
|
||||
const defaultNetwork = "default";
|
||||
if (!networks) {
|
||||
networks = [];
|
||||
@@ -376,11 +445,40 @@ export const addDokployNetworkToService = (
|
||||
return networks;
|
||||
};
|
||||
|
||||
export const removeNetworkFromService = (
|
||||
service: DefinitionsService,
|
||||
networkName: string,
|
||||
) => {
|
||||
const networks = service.networks;
|
||||
if (Array.isArray(networks)) {
|
||||
service.networks = networks.filter((n) => n !== networkName);
|
||||
} else if (networks && typeof networks === "object") {
|
||||
delete networks[networkName];
|
||||
}
|
||||
};
|
||||
|
||||
const removeDokployNetworkLabel = (service: DefinitionsService) => {
|
||||
const stripped = (labels: DefinitionsService["labels"]) => {
|
||||
if (Array.isArray(labels)) {
|
||||
return labels.filter(
|
||||
(l) =>
|
||||
l !== "traefik.docker.network=dokploy-network" &&
|
||||
l !== "traefik.swarm.network=dokploy-network",
|
||||
);
|
||||
}
|
||||
return labels;
|
||||
};
|
||||
if (service.labels) service.labels = stripped(service.labels);
|
||||
if (service.deploy?.labels)
|
||||
service.deploy.labels = stripped(service.deploy.labels);
|
||||
};
|
||||
|
||||
export const addDokployNetworkToRoot = (
|
||||
networkRoot: PropertiesNetworks | undefined,
|
||||
networkName = "dokploy-network",
|
||||
) => {
|
||||
let networks = networkRoot;
|
||||
const network = "dokploy-network";
|
||||
const network = networkName;
|
||||
|
||||
if (!networks) {
|
||||
networks = {};
|
||||
|
||||
Reference in New Issue
Block a user