mirror of
https://github.com/andwati/dokploy.git
synced 2026-10-25 14:32: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:
@@ -83,8 +83,17 @@ export const findDeploymentById = async (deploymentId: string) => {
|
||||
const deployment = await db.query.deployments.findFirst({
|
||||
where: eq(deployments.deploymentId, deploymentId),
|
||||
with: {
|
||||
application: true,
|
||||
compose: true,
|
||||
application: {
|
||||
columns: {
|
||||
applicationId: true,
|
||||
appName: true,
|
||||
name: true,
|
||||
serverId: true,
|
||||
},
|
||||
},
|
||||
compose: {
|
||||
columns: { composeId: true, appName: true, name: true, serverId: true },
|
||||
},
|
||||
schedule: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -80,7 +80,9 @@ export const findDomainById = async (domainId: string) => {
|
||||
const domain = await db.query.domains.findFirst({
|
||||
where: eq(domains.domainId, domainId),
|
||||
with: {
|
||||
application: true,
|
||||
application: {
|
||||
columns: { applicationId: true, appName: true, name: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!domain) {
|
||||
@@ -96,7 +98,9 @@ export const findDomainsByApplicationId = async (applicationId: string) => {
|
||||
const domainsArray = await db.query.domains.findMany({
|
||||
where: eq(domains.applicationId, applicationId),
|
||||
with: {
|
||||
application: true,
|
||||
application: {
|
||||
columns: { applicationId: true, appName: true, name: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -107,7 +111,9 @@ export const findDomainsByComposeId = async (composeId: string) => {
|
||||
const domainsArray = await db.query.domains.findMany({
|
||||
where: eq(domains.composeId, composeId),
|
||||
with: {
|
||||
compose: true,
|
||||
compose: {
|
||||
columns: { composeId: true, appName: true, name: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -201,18 +201,51 @@ export const findEnvironmentById = async (environmentId: string) => {
|
||||
};
|
||||
|
||||
export const findEnvironmentsByProjectId = async (projectId: string) => {
|
||||
const serviceColumns = {
|
||||
name: true,
|
||||
description: true,
|
||||
appName: true,
|
||||
createdAt: true,
|
||||
serverId: true,
|
||||
applicationStatus: true,
|
||||
} as const;
|
||||
|
||||
const projectEnvironments = await db.query.environments.findMany({
|
||||
where: eq(environments.projectId, projectId),
|
||||
orderBy: asc(environments.createdAt),
|
||||
with: {
|
||||
applications: true,
|
||||
mariadb: true,
|
||||
mongo: true,
|
||||
mysql: true,
|
||||
postgres: true,
|
||||
redis: true,
|
||||
compose: true,
|
||||
libsql: true,
|
||||
applications: {
|
||||
columns: { ...serviceColumns, applicationId: true, icon: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
mariadb: {
|
||||
columns: { ...serviceColumns, mariadbId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
mongo: {
|
||||
columns: { ...serviceColumns, mongoId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
mysql: {
|
||||
columns: { ...serviceColumns, mysqlId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
postgres: {
|
||||
columns: { ...serviceColumns, postgresId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
redis: {
|
||||
columns: { ...serviceColumns, redisId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
compose: {
|
||||
columns: { ...serviceColumns, composeId: true, composeStatus: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
libsql: {
|
||||
columns: { ...serviceColumns, libsqlId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
project: true,
|
||||
},
|
||||
columns: {
|
||||
|
||||
@@ -107,81 +107,29 @@ export const createFileMount = async (mountId: string) => {
|
||||
};
|
||||
|
||||
export const findMountById = async (mountId: string) => {
|
||||
const serviceWith = {
|
||||
columns: { serverId: true, appName: true },
|
||||
with: {
|
||||
environment: {
|
||||
columns: {},
|
||||
with: {
|
||||
project: { columns: { organizationId: true } },
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
const mount = await db.query.mounts.findFirst({
|
||||
where: eq(mounts.mountId, mountId),
|
||||
with: {
|
||||
application: {
|
||||
with: {
|
||||
environment: {
|
||||
with: {
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
compose: {
|
||||
with: {
|
||||
environment: {
|
||||
with: {
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
libsql: {
|
||||
with: {
|
||||
environment: {
|
||||
with: {
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
mariadb: {
|
||||
with: {
|
||||
environment: {
|
||||
with: {
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
mongo: {
|
||||
with: {
|
||||
environment: {
|
||||
with: {
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
mysql: {
|
||||
with: {
|
||||
environment: {
|
||||
with: {
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
postgres: {
|
||||
with: {
|
||||
environment: {
|
||||
with: {
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
redis: {
|
||||
with: {
|
||||
environment: {
|
||||
with: {
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
application: serviceWith,
|
||||
compose: serviceWith,
|
||||
libsql: serviceWith,
|
||||
mariadb: serviceWith,
|
||||
mongo: serviceWith,
|
||||
mysql: serviceWith,
|
||||
postgres: serviceWith,
|
||||
redis: serviceWith,
|
||||
},
|
||||
});
|
||||
if (!mount) {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreateNetwork, network } from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { and, eq, isNull } from "drizzle-orm";
|
||||
import { and, eq, inArray, isNull } from "drizzle-orm";
|
||||
import type { z } from "zod";
|
||||
import { IS_CLOUD } from "../constants";
|
||||
import type { ApplicationNested } from "../utils/builders";
|
||||
import { getRemoteDocker } from "../utils/servers/remote-docker";
|
||||
|
||||
// Networks managed by Docker/Dokploy itself that must never be imported
|
||||
@@ -273,14 +274,39 @@ const createDockerNetworkFromRow = async (row: typeof network.$inferSelect) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Re-creates the Docker network from the stored record, for records whose
|
||||
// network was removed from Docker outside of Dokploy
|
||||
export const recreateNetwork = async (networkId: string) => {
|
||||
const row = await findNetworkById(networkId);
|
||||
await createDockerNetworkFromRow(row);
|
||||
return row;
|
||||
};
|
||||
|
||||
export const resolveServiceNetworks = async (
|
||||
application: Partial<ApplicationNested>,
|
||||
) => {
|
||||
if (application.networkSwarm) {
|
||||
return application.networkSwarm;
|
||||
}
|
||||
|
||||
const { networkIds, detachDokployNetwork } = application;
|
||||
const rows =
|
||||
networkIds && networkIds.length > 0
|
||||
? await db.query.network.findMany({
|
||||
where: and(
|
||||
inArray(network.networkId, networkIds),
|
||||
eq(network.driver, "overlay"),
|
||||
),
|
||||
columns: { name: true },
|
||||
})
|
||||
: [];
|
||||
|
||||
const networks = detachDokployNetwork ? [] : ["dokploy-network"];
|
||||
for (const row of rows) {
|
||||
networks.push(row.name);
|
||||
}
|
||||
|
||||
return networks.map((name) => ({ Target: name }));
|
||||
};
|
||||
|
||||
export const inspectNetwork = async (networkId: string) => {
|
||||
const row = await findNetworkById(networkId);
|
||||
|
||||
|
||||
@@ -48,19 +48,60 @@ export const createProject = async (
|
||||
};
|
||||
|
||||
export const findProjectById = async (projectId: string) => {
|
||||
const serviceColumns = {
|
||||
name: true,
|
||||
description: true,
|
||||
appName: true,
|
||||
createdAt: true,
|
||||
serverId: true,
|
||||
applicationStatus: true,
|
||||
} as const;
|
||||
|
||||
const project = await db.query.projects.findFirst({
|
||||
where: eq(projects.projectId, projectId),
|
||||
with: {
|
||||
environments: {
|
||||
with: {
|
||||
applications: true,
|
||||
compose: true,
|
||||
libsql: true,
|
||||
mariadb: true,
|
||||
mongo: true,
|
||||
mysql: true,
|
||||
postgres: true,
|
||||
redis: true,
|
||||
applications: {
|
||||
columns: {
|
||||
...serviceColumns,
|
||||
applicationId: true,
|
||||
icon: true,
|
||||
},
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
compose: {
|
||||
columns: {
|
||||
...serviceColumns,
|
||||
composeId: true,
|
||||
composeStatus: true,
|
||||
},
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
libsql: {
|
||||
columns: { ...serviceColumns, libsqlId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
mariadb: {
|
||||
columns: { ...serviceColumns, mariadbId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
mongo: {
|
||||
columns: { ...serviceColumns, mongoId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
mysql: {
|
||||
columns: { ...serviceColumns, mysqlId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
postgres: {
|
||||
columns: { ...serviceColumns, postgresId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
redis: {
|
||||
columns: { ...serviceColumns, redisId: true },
|
||||
with: { server: { columns: { name: true } } },
|
||||
},
|
||||
},
|
||||
},
|
||||
projectTags: {
|
||||
@@ -107,27 +148,49 @@ export const updateProjectById = async (
|
||||
|
||||
export const validUniqueServerAppName = async (appName: string) => {
|
||||
const query = await db.query.environments.findMany({
|
||||
columns: { environmentId: true },
|
||||
with: {
|
||||
applications: {
|
||||
where: eq(applications.appName, appName),
|
||||
columns: {
|
||||
appName: true,
|
||||
},
|
||||
},
|
||||
libsql: {
|
||||
where: eq(libsql.appName, appName),
|
||||
columns: {
|
||||
appName: true,
|
||||
},
|
||||
},
|
||||
mariadb: {
|
||||
where: eq(mariadb.appName, appName),
|
||||
columns: {
|
||||
appName: true,
|
||||
},
|
||||
},
|
||||
mongo: {
|
||||
where: eq(mongo.appName, appName),
|
||||
columns: {
|
||||
appName: true,
|
||||
},
|
||||
},
|
||||
mysql: {
|
||||
where: eq(mysql.appName, appName),
|
||||
columns: {
|
||||
appName: true,
|
||||
},
|
||||
},
|
||||
postgres: {
|
||||
where: eq(postgres.appName, appName),
|
||||
columns: {
|
||||
appName: true,
|
||||
},
|
||||
},
|
||||
redis: {
|
||||
where: eq(redis.appName, appName),
|
||||
columns: {
|
||||
appName: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -20,6 +20,7 @@ import { getRemoteDocker } from "../utils/servers/remote-docker";
|
||||
import { type Application, findApplicationById } from "./application";
|
||||
import { findDeploymentById } from "./deployment";
|
||||
import type { Mount } from "./mount";
|
||||
import { resolveServiceNetworks } from "./network";
|
||||
import type { Port } from "./port";
|
||||
import type { Project } from "./project";
|
||||
import {
|
||||
@@ -257,6 +258,10 @@ const rollbackApplication = async (
|
||||
|
||||
const volumesMount = generateVolumeMounts(mounts);
|
||||
|
||||
const resolvedNetworks = await resolveServiceNetworks(
|
||||
fullContext as Parameters<typeof resolveServiceNetworks>[0],
|
||||
);
|
||||
|
||||
const {
|
||||
HealthCheck,
|
||||
RestartPolicy,
|
||||
@@ -265,7 +270,6 @@ const rollbackApplication = async (
|
||||
Mode,
|
||||
RollbackConfig,
|
||||
UpdateConfig,
|
||||
Networks,
|
||||
Ulimits,
|
||||
} = generateConfigContainer(
|
||||
fullContext as Parameters<typeof generateConfigContainer>[0],
|
||||
@@ -304,7 +308,7 @@ const rollbackApplication = async (
|
||||
...(Ulimits && { Ulimits }),
|
||||
Labels,
|
||||
},
|
||||
Networks,
|
||||
Networks: resolvedNetworks,
|
||||
RestartPolicy,
|
||||
Placement,
|
||||
Resources: {
|
||||
|
||||
@@ -100,15 +100,16 @@ export const deleteServer = async (serverId: string) => {
|
||||
export const haveActiveServices = async (serverId: string) => {
|
||||
const currentServer = await db.query.server.findFirst({
|
||||
where: eq(server.serverId, serverId),
|
||||
columns: { serverId: true },
|
||||
with: {
|
||||
applications: true,
|
||||
compose: true,
|
||||
libsql: true,
|
||||
mariadb: true,
|
||||
mongo: true,
|
||||
mysql: true,
|
||||
postgres: true,
|
||||
redis: true,
|
||||
applications: { columns: { applicationId: true } },
|
||||
compose: { columns: { composeId: true } },
|
||||
libsql: { columns: { libsqlId: true } },
|
||||
mariadb: { columns: { mariadbId: true } },
|
||||
mongo: { columns: { mongoId: true } },
|
||||
mysql: { columns: { mysqlId: true } },
|
||||
postgres: { columns: { postgresId: true } },
|
||||
redis: { columns: { redisId: true } },
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user