+
+
+
Failed to load data
-
-
+
+
);
}
@@ -105,19 +81,23 @@ export default function SwarmMonitorCard() {
return (
-
Docker Swarm Overview
-
+ Docker Swarm Overview
+ {!serverId && (
+
+ )}
-
-
- Docker Swarm Monitor
+
+
+ Monitor
@@ -200,7 +180,7 @@ export default function SwarmMonitorCard() {
{nodes.map((node) => (
-
+
))}
diff --git a/apps/dokploy/components/dashboard/swarm/servers/server-card.tsx b/apps/dokploy/components/dashboard/swarm/servers/server-card.tsx
deleted file mode 100644
index 4b732df4..00000000
--- a/apps/dokploy/components/dashboard/swarm/servers/server-card.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-import { Badge } from "@/components/ui/badge";
-import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
-import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
-import { AlertCircle, CheckCircle, HelpCircle, ServerIcon } from "lucide-react";
-import { ShowContainers } from "../../docker/show/show-containers";
-
-export interface Server {
- serverId: string;
- name: string;
- description: string | null;
- ipAddress: string;
- port: number;
- username: string;
- appName: string;
- enableDockerCleanup: boolean;
- createdAt: string;
- adminId: string;
- serverStatus: "active" | "inactive";
- command: string;
- sshKeyId: string | null;
-}
-
-interface ServerOverviewCardProps {
- server: Server;
-}
-
-export function ServerOverviewCard({ server }: ServerOverviewCardProps) {
- const getStatusIcon = (status: string) => {
- switch (status) {
- case "active":
- return
;
- case "inactive":
- return
;
- default:
- return
;
- }
- };
-
- return (
-
-
-
-
- {getStatusIcon(server.serverStatus)}
- {server.name}
-
-
- {server.serverStatus}
-
-
-
-
-
-
- IP Address:
- {server.ipAddress}
-
-
- Port:
- {server.port}
-
-
- Username:
- {server.username}
-
-
- App Name:
- {server.appName}
-
-
- Docker Cleanup:
- {server.enableDockerCleanup ? "Enabled" : "Disabled"}
-
-
- Created At:
- {new Date(server.createdAt).toLocaleString()}
-
-
-
-
-
-
-
- );
-}
diff --git a/apps/dokploy/components/dashboard/swarm/servers/servers-overview.tsx b/apps/dokploy/components/dashboard/swarm/servers/servers-overview.tsx
deleted file mode 100644
index bd54f43e..00000000
--- a/apps/dokploy/components/dashboard/swarm/servers/servers-overview.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import { Badge } from "@/components/ui/badge";
-import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
-import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
-import { api } from "@/utils/api";
-import { LoaderIcon } from "lucide-react";
-import { ServerOverviewCard } from "./server-card";
-
-export default function ServersOverview() {
- const { data: servers, isLoading } = api.server.all.useQuery();
-
- if (isLoading) {
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- IP Address:
-
-
- Port:
-
-
- Username:
-
-
- App Name:
-
-
- Docker Cleanup:
-
-
- Created At:
-
-
-
-
- >
- );
- }
-
- if (!servers) {
- return
No servers found
;
- }
- return (
-
-
-
Server Overview
-
-
-
- {servers.map((server) => (
-
- ))}
-
-
- );
-}
diff --git a/apps/dokploy/components/layouts/navigation-tabs.tsx b/apps/dokploy/components/layouts/navigation-tabs.tsx
index 46e590a7..782b9d46 100644
--- a/apps/dokploy/components/layouts/navigation-tabs.tsx
+++ b/apps/dokploy/components/layouts/navigation-tabs.tsx
@@ -62,7 +62,7 @@ const getTabMaps = (isCloud: boolean) => {
type: "docker",
},
{
- label: "Swarm & Server",
+ label: "Swarm",
description: "Manage your docker swarm and Servers",
index: "/dashboard/swarm",
isShow: ({ rol, user }) => {
diff --git a/apps/dokploy/pages/dashboard/swarm.tsx b/apps/dokploy/pages/dashboard/swarm.tsx
index 2722e0e4..15a7d793 100644
--- a/apps/dokploy/pages/dashboard/swarm.tsx
+++ b/apps/dokploy/pages/dashboard/swarm.tsx
@@ -1,7 +1,5 @@
import SwarmMonitorCard from "@/components/dashboard/swarm/monitoring-card";
-import ServersOverview from "@/components/dashboard/swarm/servers/servers-overview";
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
-import { Separator } from "@/components/ui/separator";
import { appRouter } from "@/server/api/root";
import { IS_CLOUD, validateRequest } from "@dokploy/server";
import { createServerSideHelpers } from "@trpc/react-query/server";
diff --git a/apps/dokploy/server/api/routers/swarm.ts b/apps/dokploy/server/api/routers/swarm.ts
index fe15d0ef..c5a2d4c8 100644
--- a/apps/dokploy/server/api/routers/swarm.ts
+++ b/apps/dokploy/server/api/routers/swarm.ts
@@ -8,24 +8,37 @@ 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() }))
+ getNodes: protectedProcedure
+ .input(
+ z.object({
+ serverId: z.string().optional(),
+ }),
+ )
.query(async ({ input }) => {
- return await getNodeInfo(input.nodeId);
+ return await getSwarmNodes(input.serverId);
+ }),
+ getNodeInfo: protectedProcedure
+ .input(z.object({ nodeId: z.string(), serverId: z.string().optional() }))
+ .query(async ({ input }) => {
+ return await getNodeInfo(input.nodeId, input.serverId);
+ }),
+ getNodeApps: protectedProcedure
+ .input(
+ z.object({
+ serverId: z.string().optional(),
+ }),
+ )
+ .query(async ({ input }) => {
+ return getNodeApplications(input.serverId);
}),
- getNodeApps: protectedProcedure.query(async () => {
- return getNodeApplications();
- }),
getAppInfos: protectedProcedure
.input(
z.object({
appName: z.string(),
+ serverId: z.string().optional(),
}),
)
.query(async ({ input }) => {
- return await getApplicationInfo(input.appName);
+ return await getApplicationInfo(input.appName, input.serverId);
}),
});
diff --git a/packages/server/src/services/docker.ts b/packages/server/src/services/docker.ts
index c13c71e5..60262ba1 100644
--- a/packages/server/src/services/docker.ts
+++ b/packages/server/src/services/docker.ts
@@ -225,11 +225,21 @@ export const containerRestart = async (containerId: string) => {
} catch (error) {}
};
-export const getSwarmNodes = async () => {
+export const getSwarmNodes = async (serverId?: string) => {
try {
- const { stdout, stderr } = await execAsync(
- "docker node ls --format '{{json .}}'",
- );
+ let stdout = "";
+ let stderr = "";
+ const command = "docker node ls --format '{{json .}}'";
+
+ if (serverId) {
+ const result = await execAsyncRemote(serverId, command);
+ stdout = result.stdout;
+ stderr = result.stderr;
+ } else {
+ const result = await execAsync(command);
+ stdout = result.stdout;
+ stderr = result.stderr;
+ }
if (stderr) {
console.error(`Error: ${stderr}`);
@@ -246,11 +256,20 @@ export const getSwarmNodes = async () => {
} catch (error) {}
};
-export const getNodeInfo = async (nodeId: string) => {
+export const getNodeInfo = async (nodeId: string, serverId?: string) => {
try {
- const { stdout, stderr } = await execAsync(
- `docker node inspect ${nodeId} --format '{{json .}}'`,
- );
+ const command = `docker node inspect ${nodeId} --format '{{json .}}'`;
+ let stdout = "";
+ let stderr = "";
+ if (serverId) {
+ const result = await execAsyncRemote(serverId, command);
+ stdout = result.stdout;
+ stderr = result.stderr;
+ } else {
+ const result = await execAsync(command);
+ stdout = result.stdout;
+ stderr = result.stderr;
+ }
if (stderr) {
console.error(`Error: ${stderr}`);
@@ -263,11 +282,22 @@ export const getNodeInfo = async (nodeId: string) => {
} catch (error) {}
};
-export const getNodeApplications = async () => {
+export const getNodeApplications = async (serverId?: string) => {
try {
- const { stdout, stderr } = await execAsync(
- `docker service ls --format '{{json .}}'`,
- );
+ let stdout = "";
+ let stderr = "";
+ const command = `docker service ls --format '{{json .}}'`;
+
+ if (serverId) {
+ const result = await execAsyncRemote(serverId, command);
+ stdout = result.stdout;
+ stderr = result.stderr;
+ } else {
+ const result = await execAsync(command);
+
+ stdout = result.stdout;
+ stderr = result.stderr;
+ }
if (stderr) {
console.error(`Error: ${stderr}`);
@@ -283,11 +313,24 @@ export const getNodeApplications = async () => {
} catch (error) {}
};
-export const getApplicationInfo = async (appName: string) => {
+export const getApplicationInfo = async (
+ appName: string,
+ serverId?: string,
+) => {
try {
- const { stdout, stderr } = await execAsync(
- `docker service ps ${appName} --format '{{json .}}'`,
- );
+ let stdout = "";
+ let stderr = "";
+ const command = `docker service ps ${appName} --format '{{json .}}'`;
+
+ if (serverId) {
+ const result = await execAsyncRemote(serverId, command);
+ stdout = result.stdout;
+ stderr = result.stderr;
+ } else {
+ const result = await execAsync(command);
+ stdout = result.stdout;
+ stderr = result.stderr;
+ }
if (stderr) {
console.error(`Error: ${stderr}`);