mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat(multi server): add env and toggle dashboard remote
This commit is contained in:
parent
497d45129c
commit
8bf6a22db8
@ -29,14 +29,13 @@ import { SetupServer } from "./setup-server";
|
||||
import { UpdateServer } from "./update-server";
|
||||
import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal";
|
||||
import { ShowModalLogs } from "../web-server/show-modal-logs";
|
||||
import { ToggleTraefikDashboard } from "./toggle-traefik-dashboard";
|
||||
import { EditTraefikEnv } from "../web-server/edit-traefik-env";
|
||||
export const ShowServers = () => {
|
||||
const { data, refetch } = api.server.all.useQuery();
|
||||
const { mutateAsync } = api.server.remove.useMutation();
|
||||
const { data: sshKeys } = api.sshKey.all.useQuery();
|
||||
|
||||
const { mutateAsync: toggleDashboard, isLoading: toggleDashboardIsLoading } =
|
||||
api.settings.toggleDashboard.useMutation();
|
||||
|
||||
const {
|
||||
mutateAsync: cleanDockerBuilder,
|
||||
isLoading: cleanDockerBuilderIsLoading,
|
||||
@ -63,9 +62,6 @@ export const ShowServers = () => {
|
||||
const { mutateAsync: cleanAll, isLoading: cleanAllIsLoading } =
|
||||
api.settings.cleanAll.useMutation();
|
||||
|
||||
const { data: haveTraefikDashboardPortEnabled, refetch: refetchDashboard } =
|
||||
api.settings.haveTraefikDashboardPortEnabled.useQuery();
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-6">
|
||||
<div className="space-y-2 flex flex-row justify-between items-end">
|
||||
@ -226,35 +222,18 @@ export const ShowServers = () => {
|
||||
>
|
||||
<span>Watch logs</span>
|
||||
</ShowModalLogs>
|
||||
<EditTraefikEnv serverId={server.serverId}>
|
||||
<DropdownMenuItem
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
className="w-full cursor-pointer space-x-3"
|
||||
>
|
||||
<span>Modify Env</span>
|
||||
</DropdownMenuItem>
|
||||
</EditTraefikEnv>
|
||||
<ToggleTraefikDashboard
|
||||
serverId={server.serverId}
|
||||
/>
|
||||
|
||||
{/* <DropdownMenuItem
|
||||
onClick={async () => {
|
||||
await toggleDashboard({
|
||||
enableDashboard:
|
||||
!haveTraefikDashboardPortEnabled,
|
||||
serverId: server.serverId,
|
||||
})
|
||||
.then(async () => {
|
||||
toast.success(
|
||||
`${haveTraefikDashboardPortEnabled ? "Disabled" : "Enabled"} Dashboard`,
|
||||
);
|
||||
refetchDashboard();
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error(
|
||||
`${haveTraefikDashboardPortEnabled ? "Disabled" : "Enabled"} Dashboard`,
|
||||
);
|
||||
});
|
||||
}}
|
||||
className="w-full cursor-pointer space-x-3"
|
||||
>
|
||||
<span>
|
||||
{haveTraefikDashboardPortEnabled
|
||||
? "Disable"
|
||||
: "Enable"}{" "}
|
||||
Dashboard
|
||||
</span>
|
||||
</DropdownMenuItem> */}
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuLabel>Storage</DropdownMenuLabel>
|
||||
|
@ -0,0 +1,48 @@
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
import { api } from "@/utils/api";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
serverId: string;
|
||||
}
|
||||
export const ToggleTraefikDashboard = ({ serverId }: Props) => {
|
||||
const { mutateAsync: toggleDashboard, isLoading: toggleDashboardIsLoading } =
|
||||
api.settings.toggleDashboard.useMutation();
|
||||
const { data: haveTraefikDashboardPortEnabled, refetch: refetchDashboard } =
|
||||
api.settings.haveTraefikDashboardPortEnabled.useQuery(
|
||||
{
|
||||
serverId,
|
||||
},
|
||||
{
|
||||
enabled: !!serverId,
|
||||
},
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<DropdownMenuItem
|
||||
onClick={async () => {
|
||||
await toggleDashboard({
|
||||
enableDashboard: !haveTraefikDashboardPortEnabled,
|
||||
serverId: serverId,
|
||||
})
|
||||
.then(async () => {
|
||||
toast.success(
|
||||
`${haveTraefikDashboardPortEnabled ? "Disabled" : "Enabled"} Dashboard`,
|
||||
);
|
||||
refetchDashboard();
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error(
|
||||
`${haveTraefikDashboardPortEnabled ? "Disabled" : "Enabled"} Dashboard`,
|
||||
);
|
||||
});
|
||||
}}
|
||||
className="w-full cursor-pointer space-x-3"
|
||||
>
|
||||
<span>
|
||||
{haveTraefikDashboardPortEnabled ? "Disable" : "Enable"} Dashboard
|
||||
</span>
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
);
|
||||
};
|
@ -65,6 +65,7 @@ export const EditTraefikEnv = ({ children, serverId }: Props) => {
|
||||
const onSubmit = async (data: Schema) => {
|
||||
await mutateAsync({
|
||||
env: data.env,
|
||||
serverId,
|
||||
})
|
||||
.then(async () => {
|
||||
toast.success("Traefik Env Updated");
|
||||
|
@ -88,6 +88,7 @@ export const settingsRouter = createTRPCRouter({
|
||||
.mutation(async ({ input }) => {
|
||||
await initializeTraefik({
|
||||
enableDashboard: input.enableDashboard,
|
||||
serverId: input.serverId,
|
||||
});
|
||||
return true;
|
||||
}),
|
||||
@ -357,6 +358,7 @@ export const settingsRouter = createTRPCRouter({
|
||||
|
||||
if (input?.serverId) {
|
||||
const result = await execAsyncRemote(input.serverId, command);
|
||||
console.log(result);
|
||||
return result.stdout.trim();
|
||||
}
|
||||
const result = await execAsync(command);
|
||||
@ -369,25 +371,38 @@ export const settingsRouter = createTRPCRouter({
|
||||
const envs = prepareEnvironmentVariables(input.env);
|
||||
await initializeTraefik({
|
||||
env: envs,
|
||||
serverId: input.serverId,
|
||||
});
|
||||
|
||||
return true;
|
||||
}),
|
||||
haveTraefikDashboardPortEnabled: adminProcedure.query(async () => {
|
||||
const { stdout } = await execAsync(
|
||||
"docker service inspect --format='{{json .Endpoint.Ports}}' dokploy-traefik",
|
||||
);
|
||||
haveTraefikDashboardPortEnabled: adminProcedure
|
||||
.input(apiStorage)
|
||||
.query(async ({ input }) => {
|
||||
const command = `docker service inspect --format='{{json .Endpoint.Ports}}' dokploy-traefik`;
|
||||
|
||||
const parsed: any[] = JSON.parse(stdout.trim());
|
||||
|
||||
for (const port of parsed) {
|
||||
if (port.PublishedPort === 8080) {
|
||||
return true;
|
||||
let stdout = "";
|
||||
if (input?.serverId) {
|
||||
const result = await execAsyncRemote(input.serverId, command);
|
||||
stdout = result.stdout;
|
||||
} else {
|
||||
const result = await execAsync(
|
||||
"docker service inspect --format='{{json .Endpoint.Ports}}' dokploy-traefik",
|
||||
);
|
||||
stdout = result.stdout;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}),
|
||||
const parsed: any[] = JSON.parse(stdout.trim());
|
||||
console.log(parsed);
|
||||
|
||||
for (const port of parsed) {
|
||||
if (port.PublishedPort === 8080) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}),
|
||||
|
||||
readStatsLogs: adminProcedure.input(apiReadStatsLogs).query(({ input }) => {
|
||||
const rawConfig = readMonitoringConfig();
|
||||
|
@ -135,7 +135,6 @@ export const getContainersByAppLabel = async (
|
||||
let stderr = "";
|
||||
|
||||
const command = `docker ps --filter "label=com.docker.swarm.service.name=${appName}" --format 'CONTAINER ID : {{.ID}} | Name: {{.Names}} | State: {{.State}}'`;
|
||||
console.log(command);
|
||||
if (serverId) {
|
||||
const result = await execAsyncRemote(serverId, command);
|
||||
stdout = result.stdout;
|
||||
|
@ -2,10 +2,11 @@ import { chmodSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { ContainerTaskSpec, CreateServiceOptions } from "dockerode";
|
||||
import { dump } from "js-yaml";
|
||||
import { docker, paths } from "../constants";
|
||||
import { pullImage } from "../utils/docker/utils";
|
||||
import { paths } from "../constants";
|
||||
import { pullImage, pullRemoteImage } from "../utils/docker/utils";
|
||||
import type { FileConfig } from "../utils/traefik/file-types";
|
||||
import type { MainTraefikConfig } from "../utils/traefik/types";
|
||||
import { getRemoteDocker } from "../utils/servers/remote-docker";
|
||||
|
||||
const TRAEFIK_SSL_PORT =
|
||||
Number.parseInt(process.env.TRAEFIK_SSL_PORT ?? "", 10) || 443;
|
||||
@ -14,13 +15,15 @@ const TRAEFIK_PORT = Number.parseInt(process.env.TRAEFIK_PORT ?? "", 10) || 80;
|
||||
interface TraefikOptions {
|
||||
enableDashboard?: boolean;
|
||||
env?: string[];
|
||||
serverId?: string;
|
||||
}
|
||||
|
||||
export const initializeTraefik = async ({
|
||||
enableDashboard = false,
|
||||
env,
|
||||
serverId,
|
||||
}: TraefikOptions = {}) => {
|
||||
const { MAIN_TRAEFIK_PATH, DYNAMIC_TRAEFIK_PATH } = paths();
|
||||
const { MAIN_TRAEFIK_PATH, DYNAMIC_TRAEFIK_PATH } = paths(!!serverId);
|
||||
const imageName = "traefik:v3.1.2";
|
||||
const containerName = "dokploy-traefik";
|
||||
const settings: CreateServiceOptions = {
|
||||
@ -84,8 +87,13 @@ export const initializeTraefik = async ({
|
||||
],
|
||||
},
|
||||
};
|
||||
const docker = await getRemoteDocker(serverId);
|
||||
try {
|
||||
await pullImage(imageName);
|
||||
if (serverId) {
|
||||
await pullRemoteImage(imageName, serverId);
|
||||
} else {
|
||||
await pullImage(imageName);
|
||||
}
|
||||
|
||||
const service = docker.getService(containerName);
|
||||
const inspect = await service.inspect();
|
||||
|
@ -3,7 +3,7 @@ import { docker } from "@/server/constants";
|
||||
import Dockerode from "dockerode";
|
||||
import { readSSHKey } from "../filesystem/ssh";
|
||||
|
||||
export const getRemoteDocker = async (serverId: string | null) => {
|
||||
export const getRemoteDocker = async (serverId?: string | null) => {
|
||||
if (!serverId) return docker;
|
||||
const server = await findServerById(serverId);
|
||||
if (!server.sshKeyId) return docker;
|
||||
|
Loading…
Reference in New Issue
Block a user