mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat: add swarm router and related Docker service functions
This commit is contained in:
@@ -21,6 +21,7 @@ import { mysqlRouter } from "./routers/mysql";
|
|||||||
import { notificationRouter } from "./routers/notification";
|
import { notificationRouter } from "./routers/notification";
|
||||||
import { portRouter } from "./routers/port";
|
import { portRouter } from "./routers/port";
|
||||||
import { postgresRouter } from "./routers/postgres";
|
import { postgresRouter } from "./routers/postgres";
|
||||||
|
import { previewDeploymentRouter } from "./routers/preview-deployment";
|
||||||
import { projectRouter } from "./routers/project";
|
import { projectRouter } from "./routers/project";
|
||||||
import { redirectsRouter } from "./routers/redirects";
|
import { redirectsRouter } from "./routers/redirects";
|
||||||
import { redisRouter } from "./routers/redis";
|
import { redisRouter } from "./routers/redis";
|
||||||
@@ -30,8 +31,8 @@ import { serverRouter } from "./routers/server";
|
|||||||
import { settingsRouter } from "./routers/settings";
|
import { settingsRouter } from "./routers/settings";
|
||||||
import { sshRouter } from "./routers/ssh-key";
|
import { sshRouter } from "./routers/ssh-key";
|
||||||
import { stripeRouter } from "./routers/stripe";
|
import { stripeRouter } from "./routers/stripe";
|
||||||
|
import { swarmRouter } from "./routers/swarm";
|
||||||
import { userRouter } from "./routers/user";
|
import { userRouter } from "./routers/user";
|
||||||
import { previewDeploymentRouter } from "./routers/preview-deployment";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the primary router for your server.
|
* This is the primary router for your server.
|
||||||
@@ -73,6 +74,7 @@ export const appRouter = createTRPCRouter({
|
|||||||
github: githubRouter,
|
github: githubRouter,
|
||||||
server: serverRouter,
|
server: serverRouter,
|
||||||
stripe: stripeRouter,
|
stripe: stripeRouter,
|
||||||
|
swarm: swarmRouter,
|
||||||
});
|
});
|
||||||
|
|
||||||
// export type definition of API
|
// export type definition of API
|
||||||
|
|||||||
31
apps/dokploy/server/api/routers/swarm.ts
Normal file
31
apps/dokploy/server/api/routers/swarm.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import {
|
||||||
|
getApplicationInfo,
|
||||||
|
getNodeApplications,
|
||||||
|
getNodeInfo,
|
||||||
|
getSwarmNodes,
|
||||||
|
} from "@dokploy/server";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { createTRPCRouter, protectedProcedure } from "../trpc";
|
||||||
|
|
||||||
|
export const swarmRouter = createTRPCRouter({
|
||||||
|
getNodes: protectedProcedure.query(async () => {
|
||||||
|
return await getSwarmNodes();
|
||||||
|
}),
|
||||||
|
getNodeInfo: protectedProcedure
|
||||||
|
.input(z.object({ nodeId: z.string() }))
|
||||||
|
.query(async ({ input }) => {
|
||||||
|
return await getNodeInfo(input.nodeId);
|
||||||
|
}),
|
||||||
|
getNodeApps: protectedProcedure.query(async () => {
|
||||||
|
return getNodeApplications();
|
||||||
|
}),
|
||||||
|
getAppInfos: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
appName: z.string(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ input }) => {
|
||||||
|
return await getApplicationInfo(input.appName);
|
||||||
|
}),
|
||||||
|
});
|
||||||
@@ -224,3 +224,106 @@ export const containerRestart = async (containerId: string) => {
|
|||||||
return config;
|
return config;
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getSwarmNodes = async () => {
|
||||||
|
try {
|
||||||
|
const { stdout, stderr } = await execAsync(
|
||||||
|
"docker node ls --format '{{json .}}'",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (stderr) {
|
||||||
|
console.error(`Error: ${stderr}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodes = JSON.parse(stdout);
|
||||||
|
|
||||||
|
const nodesArray = stdout
|
||||||
|
.trim()
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => JSON.parse(line));
|
||||||
|
return nodesArray;
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getNodeInfo = async (nodeId: string) => {
|
||||||
|
try {
|
||||||
|
const { stdout, stderr } = await execAsync(
|
||||||
|
`docker node inspect ${nodeId} --format '{{json .}}'`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (stderr) {
|
||||||
|
console.error(`Error: ${stderr}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeInfo = JSON.parse(stdout);
|
||||||
|
|
||||||
|
return nodeInfo;
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getNodeApplications = async () => {
|
||||||
|
try {
|
||||||
|
// TODO: Implement this
|
||||||
|
// const { stdout, stderr } = await execAsync(
|
||||||
|
// `docker service ls --format '{{json .}}'`
|
||||||
|
// );
|
||||||
|
|
||||||
|
const stdout = `{"ID":"pxvnj68dxom9","Image":"dokploy/dokploy:latest","Mode":"replicated","Name":"dokploy","Ports":"","Replicas":"1/1"}
|
||||||
|
{"ID":"1sweo6dr2vrn","Image":"postgres:16","Mode":"replicated","Name":"dokploy-postgres","Ports":"","Replicas":"1/1"}
|
||||||
|
{"ID":"tnl2fck3rbop","Image":"redis:7","Mode":"replicated","Name":"dokploy-redis","Ports":"","Replicas":"1/1"}
|
||||||
|
{"ID":"o9ady4y1p96x","Image":"traefik:v3.1.2","Mode":"replicated","Name":"dokploy-traefik","Ports":"","Replicas":"1/1"}
|
||||||
|
{"ID":"rsxe3l71h9y4","Image":"esports-manager-api-eg8t7w:latest","Mode":"replicated","Name":"esports-manager-api-eg8t7w","Ports":"","Replicas":"1/1"}
|
||||||
|
{"ID":"fw52vzcw5dc0","Image":"team-synix-admin-dvgspy:latest","Mode":"replicated","Name":"team-synix-admin-dvgspy","Ports":"","Replicas":"1/1"}
|
||||||
|
{"ID":"551bwmtd6b4t","Image":"team-synix-leaderboard-9vx8ca:latest","Mode":"replicated","Name":"team-synix-leaderboard-9vx8ca","Ports":"","Replicas":"1/1"}
|
||||||
|
{"ID":"h1eyg3g1tyn3","Image":"postgres:15","Mode":"replicated","Name":"team-synix-webpage-db-fkivnf","Ports":"","Replicas":"1/1"}`;
|
||||||
|
|
||||||
|
// if (stderr) {
|
||||||
|
// console.error(`Error: ${stderr}`);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
const appArray = stdout
|
||||||
|
.trim()
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => JSON.parse(line));
|
||||||
|
|
||||||
|
console.log(appArray);
|
||||||
|
return appArray;
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getApplicationInfo = async (appName: string) => {
|
||||||
|
try {
|
||||||
|
// TODO: Implement this
|
||||||
|
// const { stdout, stderr } = await execAsync(
|
||||||
|
// `docker service ps ${appName} --format '{{json .}}'`
|
||||||
|
// );
|
||||||
|
|
||||||
|
const stdout = `{"CurrentState":"Running 2 weeks ago","DesiredState":"Running","Error":"","ID":"nx8jxlmb8niw","Image":"postgres:16","Name":"dokploy-postgres.1","Node":"v2202411192718297480","Ports":""}
|
||||||
|
{"CurrentState":"Running 2 weeks ago","DesiredState":"Running","Error":"","ID":"s288g9lwtvi4","Image":"redis:7","Name":"dokploy-redis.1","Node":"v2202411192718297480","Ports":""}
|
||||||
|
{"CurrentState":"Running 2 weeks ago","DesiredState":"Running","Error":"","ID":"2vcmejz51b23","Image":"traefik:v3.1.2","Name":"dokploy-traefik.1","Node":"v2202411192718297480","Ports":"*:80-\u003e80/tcp,*:80-\u003e80/tcp,*:443-\u003e443/tcp,*:443-\u003e443/tcp"}
|
||||||
|
{"CurrentState":"Running 26 hours ago","DesiredState":"Running","Error":"","ID":"79iatnbsm2um","Image":"dokploy/dokploy:latest","Name":"dokploy.1","Node":"v2202411192718297480","Ports":"*:3000-\u003e3000/tcp,*:3000-\u003e3000/tcp"}
|
||||||
|
{"CurrentState":"Shutdown 26 hours ago","DesiredState":"Shutdown","Error":"","ID":"zcwxs501zs7w","Image":"dokploy/dokploy:latest","Name":"dokploy.1","Node":"v2202411192718297480","Ports":""}
|
||||||
|
{"CurrentState":"Shutdown 7 days ago","DesiredState":"Shutdown","Error":"","ID":"t59qhkoenno4","Image":"dokploy/dokploy:latest","Name":"dokploy.1","Node":"v2202411192718297480","Ports":""}
|
||||||
|
{"CurrentState":"Shutdown 7 days ago","DesiredState":"Shutdown","Error":"","ID":"o5xtcuj6um7e","Image":"dokploy/dokploy:latest","Name":"dokploy.1","Node":"v2202411192718297480","Ports":""}
|
||||||
|
{"CurrentState":"Running 2 weeks ago","DesiredState":"Running","Error":"","ID":"q1lr9rmf452g","Image":"esports-manager-api-eg8t7w:latest","Name":"esports-manager-api-eg8t7w.1","Node":"v2202411192718297480","Ports":""}
|
||||||
|
{"CurrentState":"Shutdown 2 weeks ago","DesiredState":"Shutdown","Error":"","ID":"y9ixpg6b8qdo","Image":"esports-manager-api-eg8t7w:latest","Name":"esports-manager-api-eg8t7w.1","Node":"v2202411192718297480","Ports":""}
|
||||||
|
{"CurrentState":"Running 24 hours ago","DesiredState":"Running","Error":"","ID":"xgcb919qjg1a","Image":"team-synix-admin-dvgspy:latest","Name":"team-synix-admin-dvgspy.1","Node":"v2202411192718297480","Ports":""}
|
||||||
|
{"CurrentState":"Running 26 hours ago","DesiredState":"Running","Error":"","ID":"7yi95wh8zhh6","Image":"team-synix-leaderboard-9vx8ca:latest","Name":"team-synix-leaderboard-9vx8ca.1","Node":"v2202411192718297480","Ports":""}
|
||||||
|
{"CurrentState":"Running 2 weeks ago","DesiredState":"Running","Error":"","ID":"89yzsnghpbq6","Image":"postgres:15","Name":"team-synix-webpage-db-fkivnf.1","Node":"v2202411192718297480","Ports":""}`;
|
||||||
|
|
||||||
|
// if (stderr) {
|
||||||
|
// console.error(`Error: ${stderr}`);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
const appArray = stdout
|
||||||
|
.trim()
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => JSON.parse(line));
|
||||||
|
|
||||||
|
return appArray;
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user