mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat: add reload, stop and start in remote server
This commit is contained in:
@@ -7,7 +7,7 @@ import {
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { File } from "lucide-react";
|
||||
import { File, Loader2 } from "lucide-react";
|
||||
import React from "react";
|
||||
import { UpdateTraefikConfig } from "./update-traefik-config";
|
||||
interface Props {
|
||||
@@ -15,7 +15,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export const ShowTraefikConfig = ({ applicationId }: Props) => {
|
||||
const { data } = api.application.readTraefikConfig.useQuery(
|
||||
const { data, isLoading } = api.application.readTraefikConfig.useQuery(
|
||||
{
|
||||
applicationId,
|
||||
},
|
||||
@@ -35,7 +35,12 @@ export const ShowTraefikConfig = ({ applicationId }: Props) => {
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
{data === null ? (
|
||||
{isLoading ? (
|
||||
<span className="text-base text-muted-foreground flex flex-row gap-3 items-center justify-center min-h-[10vh]">
|
||||
Loading...
|
||||
<Loader2 className="animate-spin" />
|
||||
</span>
|
||||
) : !data ? (
|
||||
<div className="flex w-full flex-col items-center justify-center gap-3 pt-10">
|
||||
<File className="size-8 text-muted-foreground" />
|
||||
<span className="text-base text-muted-foreground">
|
||||
|
||||
@@ -298,11 +298,7 @@ export const AddDomain = ({
|
||||
</form>
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
isLoading={form.formState.isSubmitting}
|
||||
form="hook-form"
|
||||
type="submit"
|
||||
>
|
||||
<Button isLoading={isLoading} form="hook-form" type="submit">
|
||||
{dictionary.submit}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
18
apps/dokploy/pages/api/teapot.ts
Normal file
18
apps/dokploy/pages/api/teapot.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { NextRequest } from "next/server";
|
||||
import { renderToString } from "react-dom/server";
|
||||
import Page418 from "../hola"; // Importa la página 418
|
||||
|
||||
export const GET = async (req: NextRequest) => {
|
||||
// Renderiza el componente de la página 418 como HTML
|
||||
const htmlContent = renderToString(Page418());
|
||||
|
||||
// Devuelve la respuesta con el código de estado HTTP 418
|
||||
return new Response(htmlContent, {
|
||||
headers: {
|
||||
"Content-Type": "text/html",
|
||||
},
|
||||
status: 418,
|
||||
});
|
||||
};
|
||||
|
||||
export default GET;
|
||||
3
apps/dokploy/pages/hola.tsx
Normal file
3
apps/dokploy/pages/hola.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function hola() {
|
||||
return <div>hola</div>;
|
||||
}
|
||||
@@ -36,6 +36,7 @@ import { serverRouter } from "./routers/server";
|
||||
*
|
||||
* All routers added in /api/routers should be manually added here.
|
||||
*/
|
||||
|
||||
export const appRouter = createTRPCRouter({
|
||||
admin: adminRouter,
|
||||
docker: dockerRouter,
|
||||
|
||||
@@ -27,7 +27,9 @@ import { enqueueDeploymentJob, myQueue } from "@/server/queues/queueSetup";
|
||||
import {
|
||||
removeService,
|
||||
startService,
|
||||
startServiceRemote,
|
||||
stopService,
|
||||
stopServiceRemote,
|
||||
} from "@/server/utils/docker/utils";
|
||||
import {
|
||||
removeDirectoryCode,
|
||||
@@ -38,6 +40,7 @@ import {
|
||||
readRemoteConfig,
|
||||
removeTraefikConfig,
|
||||
writeConfig,
|
||||
writeConfigRemote,
|
||||
} from "@/server/utils/traefik/application";
|
||||
import { deleteAllMiddlewares } from "@/server/utils/traefik/middleware";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
@@ -53,7 +56,6 @@ import {
|
||||
} from "../services/application";
|
||||
import { removeDeployments } from "../services/deployment";
|
||||
import { addNewService, checkServiceAccess } from "../services/user";
|
||||
|
||||
import { unzipDrop } from "@/server/utils/builders/drop";
|
||||
import { uploadFileSchema } from "@/utils/schema";
|
||||
|
||||
@@ -97,9 +99,19 @@ export const applicationRouter = createTRPCRouter({
|
||||
reload: protectedProcedure
|
||||
.input(apiReloadApplication)
|
||||
.mutation(async ({ input }) => {
|
||||
await stopService(input.appName);
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.serverId) {
|
||||
await stopServiceRemote(application.serverId, input.appName);
|
||||
} else {
|
||||
await stopService(input.appName);
|
||||
}
|
||||
await updateApplicationStatus(input.applicationId, "idle");
|
||||
await startService(input.appName);
|
||||
|
||||
if (application.serverId) {
|
||||
await startServiceRemote(application.serverId, input.appName);
|
||||
} else {
|
||||
await startService(input.appName);
|
||||
}
|
||||
await updateApplicationStatus(input.applicationId, "done");
|
||||
return true;
|
||||
}),
|
||||
@@ -143,7 +155,11 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input }) => {
|
||||
const service = await findApplicationById(input.applicationId);
|
||||
await stopService(service.appName);
|
||||
if (service.serverId) {
|
||||
await stopServiceRemote(service.serverId, service.appName);
|
||||
} else {
|
||||
await stopService(service.appName);
|
||||
}
|
||||
await updateApplicationStatus(input.applicationId, "idle");
|
||||
|
||||
return service;
|
||||
@@ -153,8 +169,11 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input }) => {
|
||||
const service = await findApplicationById(input.applicationId);
|
||||
|
||||
await startService(service.appName);
|
||||
if (service.serverId) {
|
||||
await startServiceRemote(service.serverId, service.appName);
|
||||
} else {
|
||||
await startService(service.appName);
|
||||
}
|
||||
await updateApplicationStatus(input.applicationId, "done");
|
||||
|
||||
return service;
|
||||
@@ -387,7 +406,16 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(z.object({ applicationId: z.string(), traefikConfig: z.string() }))
|
||||
.mutation(async ({ input }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
writeConfig(application.appName, input.traefikConfig);
|
||||
|
||||
if (application.serverId) {
|
||||
await writeConfigRemote(
|
||||
application.serverId,
|
||||
application.appName,
|
||||
input.traefikConfig,
|
||||
);
|
||||
} else {
|
||||
writeConfig(application.appName, input.traefikConfig);
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
readAppMonitoring: protectedProcedure
|
||||
|
||||
@@ -12,7 +12,9 @@ import {
|
||||
import {
|
||||
removeService,
|
||||
startService,
|
||||
startServiceRemote,
|
||||
stopService,
|
||||
stopServiceRemote,
|
||||
} from "@/server/utils/docker/utils";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import {
|
||||
@@ -72,8 +74,11 @@ export const mariadbRouter = createTRPCRouter({
|
||||
.input(apiFindOneMariaDB)
|
||||
.mutation(async ({ input }) => {
|
||||
const service = await findMariadbById(input.mariadbId);
|
||||
|
||||
await startService(service.appName);
|
||||
if (service.serverId) {
|
||||
await startServiceRemote(service.serverId, service.appName);
|
||||
} else {
|
||||
await startService(service.appName);
|
||||
}
|
||||
await updateMariadbById(input.mariadbId, {
|
||||
applicationStatus: "done",
|
||||
});
|
||||
@@ -83,13 +88,18 @@ export const mariadbRouter = createTRPCRouter({
|
||||
stop: protectedProcedure
|
||||
.input(apiFindOneMariaDB)
|
||||
.mutation(async ({ input }) => {
|
||||
const mongo = await findMariadbById(input.mariadbId);
|
||||
await stopService(mongo.appName);
|
||||
const mariadb = await findMariadbById(input.mariadbId);
|
||||
|
||||
if (mariadb.serverId) {
|
||||
await stopServiceRemote(mariadb.serverId, mariadb.appName);
|
||||
} else {
|
||||
await stopService(mariadb.appName);
|
||||
}
|
||||
await updateMariadbById(input.mariadbId, {
|
||||
applicationStatus: "idle",
|
||||
});
|
||||
|
||||
return mongo;
|
||||
return mariadb;
|
||||
}),
|
||||
saveExternalPort: protectedProcedure
|
||||
.input(apiSaveExternalPortMariaDB)
|
||||
@@ -156,11 +166,21 @@ export const mariadbRouter = createTRPCRouter({
|
||||
reload: protectedProcedure
|
||||
.input(apiResetMariadb)
|
||||
.mutation(async ({ input }) => {
|
||||
await stopService(input.appName);
|
||||
const mariadb = await findMariadbById(input.mariadbId);
|
||||
if (mariadb.serverId) {
|
||||
await stopServiceRemote(mariadb.serverId, mariadb.appName);
|
||||
} else {
|
||||
await stopService(mariadb.appName);
|
||||
}
|
||||
await updateMariadbById(input.mariadbId, {
|
||||
applicationStatus: "idle",
|
||||
});
|
||||
await startService(input.appName);
|
||||
|
||||
if (mariadb.serverId) {
|
||||
await startServiceRemote(mariadb.serverId, mariadb.appName);
|
||||
} else {
|
||||
await startService(mariadb.appName);
|
||||
}
|
||||
await updateMariadbById(input.mariadbId, {
|
||||
applicationStatus: "done",
|
||||
});
|
||||
|
||||
@@ -12,7 +12,9 @@ import {
|
||||
import {
|
||||
removeService,
|
||||
startService,
|
||||
startServiceRemote,
|
||||
stopService,
|
||||
stopServiceRemote,
|
||||
} from "@/server/utils/docker/utils";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import {
|
||||
@@ -74,7 +76,11 @@ export const mongoRouter = createTRPCRouter({
|
||||
.mutation(async ({ input }) => {
|
||||
const service = await findMongoById(input.mongoId);
|
||||
|
||||
await startService(service.appName);
|
||||
if (service.serverId) {
|
||||
await startServiceRemote(service.serverId, service.appName);
|
||||
} else {
|
||||
await startService(service.appName);
|
||||
}
|
||||
await updateMongoById(input.mongoId, {
|
||||
applicationStatus: "done",
|
||||
});
|
||||
@@ -85,7 +91,12 @@ export const mongoRouter = createTRPCRouter({
|
||||
.input(apiFindOneMongo)
|
||||
.mutation(async ({ input }) => {
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
await stopService(mongo.appName);
|
||||
|
||||
if (mongo.serverId) {
|
||||
await stopServiceRemote(mongo.serverId, mongo.appName);
|
||||
} else {
|
||||
await stopService(mongo.appName);
|
||||
}
|
||||
await updateMongoById(input.mongoId, {
|
||||
applicationStatus: "idle",
|
||||
});
|
||||
@@ -119,11 +130,21 @@ export const mongoRouter = createTRPCRouter({
|
||||
reload: protectedProcedure
|
||||
.input(apiResetMongo)
|
||||
.mutation(async ({ input }) => {
|
||||
await stopService(input.appName);
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
if (mongo.serverId) {
|
||||
await stopServiceRemote(mongo.serverId, mongo.appName);
|
||||
} else {
|
||||
await stopService(mongo.appName);
|
||||
}
|
||||
await updateMongoById(input.mongoId, {
|
||||
applicationStatus: "idle",
|
||||
});
|
||||
await startService(input.appName);
|
||||
|
||||
if (mongo.serverId) {
|
||||
await startServiceRemote(mongo.serverId, mongo.appName);
|
||||
} else {
|
||||
await startService(mongo.appName);
|
||||
}
|
||||
await updateMongoById(input.mongoId, {
|
||||
applicationStatus: "done",
|
||||
});
|
||||
|
||||
@@ -12,7 +12,9 @@ import {
|
||||
import {
|
||||
removeService,
|
||||
startService,
|
||||
startServiceRemote,
|
||||
stopService,
|
||||
stopServiceRemote,
|
||||
} from "@/server/utils/docker/utils";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { createMount } from "../services/mount";
|
||||
@@ -73,7 +75,11 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.mutation(async ({ input }) => {
|
||||
const service = await findMySqlById(input.mysqlId);
|
||||
|
||||
await startService(service.appName);
|
||||
if (service.serverId) {
|
||||
await startServiceRemote(service.serverId, service.appName);
|
||||
} else {
|
||||
await startService(service.appName);
|
||||
}
|
||||
await updateMySqlById(input.mysqlId, {
|
||||
applicationStatus: "done",
|
||||
});
|
||||
@@ -84,7 +90,11 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.input(apiFindOneMySql)
|
||||
.mutation(async ({ input }) => {
|
||||
const mongo = await findMySqlById(input.mysqlId);
|
||||
await stopService(mongo.appName);
|
||||
if (mongo.serverId) {
|
||||
await stopServiceRemote(mongo.serverId, mongo.appName);
|
||||
} else {
|
||||
await stopService(mongo.appName);
|
||||
}
|
||||
await updateMySqlById(input.mysqlId, {
|
||||
applicationStatus: "idle",
|
||||
});
|
||||
@@ -118,11 +128,20 @@ export const mysqlRouter = createTRPCRouter({
|
||||
reload: protectedProcedure
|
||||
.input(apiResetMysql)
|
||||
.mutation(async ({ input }) => {
|
||||
await stopService(input.appName);
|
||||
const mysql = await findMySqlById(input.mysqlId);
|
||||
if (mysql.serverId) {
|
||||
await stopServiceRemote(mysql.serverId, mysql.appName);
|
||||
} else {
|
||||
await stopService(mysql.appName);
|
||||
}
|
||||
await updateMySqlById(input.mysqlId, {
|
||||
applicationStatus: "idle",
|
||||
});
|
||||
await startService(input.appName);
|
||||
if (mysql.serverId) {
|
||||
await startServiceRemote(mysql.serverId, mysql.appName);
|
||||
} else {
|
||||
await startService(mysql.appName);
|
||||
}
|
||||
await updateMySqlById(input.mysqlId, {
|
||||
applicationStatus: "done",
|
||||
});
|
||||
|
||||
@@ -12,7 +12,9 @@ import {
|
||||
import {
|
||||
removeService,
|
||||
startService,
|
||||
startServiceRemote,
|
||||
stopService,
|
||||
stopServiceRemote,
|
||||
} from "@/server/utils/docker/utils";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { createMount } from "../services/mount";
|
||||
@@ -74,7 +76,11 @@ export const postgresRouter = createTRPCRouter({
|
||||
.mutation(async ({ input }) => {
|
||||
const service = await findPostgresById(input.postgresId);
|
||||
|
||||
await startService(service.appName);
|
||||
if (service.serverId) {
|
||||
await startServiceRemote(service.serverId, service.appName);
|
||||
} else {
|
||||
await startService(service.appName);
|
||||
}
|
||||
await updatePostgresById(input.postgresId, {
|
||||
applicationStatus: "done",
|
||||
});
|
||||
@@ -85,7 +91,11 @@ export const postgresRouter = createTRPCRouter({
|
||||
.input(apiFindOnePostgres)
|
||||
.mutation(async ({ input }) => {
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
await stopService(postgres.appName);
|
||||
if (postgres.serverId) {
|
||||
await stopServiceRemote(postgres.serverId, postgres.appName);
|
||||
} else {
|
||||
await stopService(postgres.appName);
|
||||
}
|
||||
await updatePostgresById(input.postgresId, {
|
||||
applicationStatus: "idle",
|
||||
});
|
||||
@@ -152,11 +162,21 @@ export const postgresRouter = createTRPCRouter({
|
||||
reload: protectedProcedure
|
||||
.input(apiResetPostgres)
|
||||
.mutation(async ({ input }) => {
|
||||
await stopService(input.appName);
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
if (postgres.serverId) {
|
||||
await stopServiceRemote(postgres.serverId, postgres.appName);
|
||||
} else {
|
||||
await stopService(postgres.appName);
|
||||
}
|
||||
await updatePostgresById(input.postgresId, {
|
||||
applicationStatus: "idle",
|
||||
});
|
||||
await startService(input.appName);
|
||||
|
||||
if (postgres.serverId) {
|
||||
await startServiceRemote(postgres.serverId, postgres.appName);
|
||||
} else {
|
||||
await startService(postgres.appName);
|
||||
}
|
||||
await updatePostgresById(input.postgresId, {
|
||||
applicationStatus: "done",
|
||||
});
|
||||
|
||||
@@ -12,7 +12,9 @@ import {
|
||||
import {
|
||||
removeService,
|
||||
startService,
|
||||
startServiceRemote,
|
||||
stopService,
|
||||
stopServiceRemote,
|
||||
} from "@/server/utils/docker/utils";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { createMount } from "../services/mount";
|
||||
@@ -69,7 +71,12 @@ export const redisRouter = createTRPCRouter({
|
||||
.input(apiFindOneRedis)
|
||||
.mutation(async ({ input }) => {
|
||||
const redis = await findRedisById(input.redisId);
|
||||
await startService(redis.appName);
|
||||
|
||||
if (redis.serverId) {
|
||||
await startServiceRemote(redis.serverId, redis.appName);
|
||||
} else {
|
||||
await startService(redis.appName);
|
||||
}
|
||||
await updateRedisById(input.redisId, {
|
||||
applicationStatus: "done",
|
||||
});
|
||||
@@ -79,11 +86,21 @@ export const redisRouter = createTRPCRouter({
|
||||
reload: protectedProcedure
|
||||
.input(apiResetRedis)
|
||||
.mutation(async ({ input }) => {
|
||||
await stopService(input.appName);
|
||||
const redis = await findRedisById(input.redisId);
|
||||
if (redis.serverId) {
|
||||
await stopServiceRemote(redis.serverId, redis.appName);
|
||||
} else {
|
||||
await stopService(redis.appName);
|
||||
}
|
||||
await updateRedisById(input.redisId, {
|
||||
applicationStatus: "idle",
|
||||
});
|
||||
await startService(input.appName);
|
||||
|
||||
if (redis.serverId) {
|
||||
await startServiceRemote(redis.serverId, redis.appName);
|
||||
} else {
|
||||
await startService(redis.appName);
|
||||
}
|
||||
await updateRedisById(input.redisId, {
|
||||
applicationStatus: "done",
|
||||
});
|
||||
@@ -93,13 +110,17 @@ export const redisRouter = createTRPCRouter({
|
||||
stop: protectedProcedure
|
||||
.input(apiFindOneRedis)
|
||||
.mutation(async ({ input }) => {
|
||||
const mongo = await findRedisById(input.redisId);
|
||||
await stopService(mongo.appName);
|
||||
const redis = await findRedisById(input.redisId);
|
||||
if (redis.serverId) {
|
||||
await stopServiceRemote(redis.serverId, redis.appName);
|
||||
} else {
|
||||
await stopService(redis.appName);
|
||||
}
|
||||
await updateRedisById(input.redisId, {
|
||||
applicationStatus: "idle",
|
||||
});
|
||||
|
||||
return mongo;
|
||||
return redis;
|
||||
}),
|
||||
saveExternalPort: protectedProcedure
|
||||
.input(apiSaveExternalPortRedis)
|
||||
|
||||
@@ -169,7 +169,6 @@ export const deployApplication = async ({
|
||||
`;
|
||||
if (application.sourceType === "github") {
|
||||
command += await getGithubCloneCommand(application, deployment.logPath);
|
||||
console.log(application);
|
||||
command += getBuildCommand(application, deployment.logPath);
|
||||
} else if (application.sourceType === "gitlab") {
|
||||
command += await getGitlabCloneCommand(application, deployment.logPath);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { APPLICATIONS_PATH, docker } from "@/server/constants";
|
||||
import type { ContainerInfo, ResourceRequirements } from "dockerode";
|
||||
import { parse } from "dotenv";
|
||||
import type { ApplicationNested } from "../builders";
|
||||
import { execAsync } from "../process/execAsync";
|
||||
import { execAsync, execAsyncRemote } from "../process/execAsync";
|
||||
import { getRemoteDocker } from "../servers/remote-docker";
|
||||
|
||||
interface RegistryAuth {
|
||||
@@ -116,6 +116,15 @@ export const stopService = async (appName: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const stopServiceRemote = async (serverId: string, appName: string) => {
|
||||
try {
|
||||
await execAsyncRemote(serverId, `docker service scale ${appName}=0 `);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
export const getContainerByName = (name: string): Promise<ContainerInfo> => {
|
||||
const opts = {
|
||||
limit: 1,
|
||||
@@ -196,6 +205,15 @@ export const startService = async (appName: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const startServiceRemote = async (serverId: string, appName: string) => {
|
||||
try {
|
||||
await execAsyncRemote(serverId, `docker service scale ${appName}=1 `);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const removeService = async (appName: string) => {
|
||||
try {
|
||||
await execAsync(`docker service rm ${appName}`);
|
||||
|
||||
@@ -145,6 +145,19 @@ export const writeConfig = (appName: string, traefikConfig: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const writeConfigRemote = async (
|
||||
serverId: string,
|
||||
appName: string,
|
||||
traefikConfig: string,
|
||||
) => {
|
||||
try {
|
||||
const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`);
|
||||
await execAsyncRemote(serverId, `echo '${traefikConfig}' > ${configPath}`);
|
||||
} catch (e) {
|
||||
console.error("Error saving the YAML config file:", e);
|
||||
}
|
||||
};
|
||||
|
||||
export const writeTraefikConfigInPath = (
|
||||
pathFile: string,
|
||||
traefikConfig: string,
|
||||
|
||||
Reference in New Issue
Block a user