diff --git a/apps/dokploy/server/api/routers/docker.ts b/apps/dokploy/server/api/routers/docker.ts
index dd322e6c3..d319e5a16 100644
--- a/apps/dokploy/server/api/routers/docker.ts
+++ b/apps/dokploy/server/api/routers/docker.ts
@@ -1,6 +1,9 @@
import {
+ containerKill,
containerRemove,
containerRestart,
+ containerStart,
+ containerStop,
findServerById,
getConfig,
getContainers,
@@ -35,24 +38,108 @@ export const dockerRouter = createTRPCRouter({
return await getContainers(input.serverId);
}),
- restartContainer: withPermission("docker", "read")
+ restartContainer: withPermission("service", "read")
.input(
z.object({
containerId: z
.string()
.min(1)
.regex(containerIdRegex, "Invalid container id."),
+ serverId: z.string().optional(),
}),
)
.mutation(async ({ input, ctx }) => {
- const result = await containerRestart(input.containerId);
+ if (input.serverId) {
+ const server = await findServerById(input.serverId);
+ if (server.organizationId !== ctx.session?.activeOrganizationId) {
+ throw new TRPCError({ code: "UNAUTHORIZED" });
+ }
+ }
+ await containerRestart(input.containerId, input.serverId);
await audit(ctx, {
action: "start",
resourceType: "docker",
resourceId: input.containerId,
resourceName: input.containerId,
});
- return result;
+ }),
+
+ startContainer: withPermission("service", "read")
+ .input(
+ z.object({
+ containerId: z
+ .string()
+ .min(1)
+ .regex(containerIdRegex, "Invalid container id."),
+ serverId: z.string().optional(),
+ }),
+ )
+ .mutation(async ({ input, ctx }) => {
+ if (input.serverId) {
+ const server = await findServerById(input.serverId);
+ if (server.organizationId !== ctx.session?.activeOrganizationId) {
+ throw new TRPCError({ code: "UNAUTHORIZED" });
+ }
+ }
+ await containerStart(input.containerId, input.serverId);
+ await audit(ctx, {
+ action: "start",
+ resourceType: "docker",
+ resourceId: input.containerId,
+ resourceName: input.containerId,
+ });
+ }),
+
+ stopContainer: withPermission("service", "read")
+ .input(
+ z.object({
+ containerId: z
+ .string()
+ .min(1)
+ .regex(containerIdRegex, "Invalid container id."),
+ serverId: z.string().optional(),
+ }),
+ )
+ .mutation(async ({ input, ctx }) => {
+ if (input.serverId) {
+ const server = await findServerById(input.serverId);
+ if (server.organizationId !== ctx.session?.activeOrganizationId) {
+ throw new TRPCError({ code: "UNAUTHORIZED" });
+ }
+ }
+ await containerStop(input.containerId, input.serverId);
+ await audit(ctx, {
+ action: "stop",
+ resourceType: "docker",
+ resourceId: input.containerId,
+ resourceName: input.containerId,
+ });
+ }),
+
+ killContainer: withPermission("service", "read")
+ .input(
+ z.object({
+ containerId: z
+ .string()
+ .min(1)
+ .regex(containerIdRegex, "Invalid container id."),
+ serverId: z.string().optional(),
+ }),
+ )
+ .mutation(async ({ input, ctx }) => {
+ if (input.serverId) {
+ const server = await findServerById(input.serverId);
+ if (server.organizationId !== ctx.session?.activeOrganizationId) {
+ throw new TRPCError({ code: "UNAUTHORIZED" });
+ }
+ }
+ await containerKill(input.containerId, input.serverId);
+ await audit(ctx, {
+ action: "stop",
+ resourceType: "docker",
+ resourceId: input.containerId,
+ resourceName: input.containerId,
+ });
}),
removeContainer: withPermission("docker", "read")
diff --git a/packages/server/src/services/docker.ts b/packages/server/src/services/docker.ts
index eb218b1e1..e49adbb94 100644
--- a/packages/server/src/services/docker.ts
+++ b/packages/server/src/services/docker.ts
@@ -417,21 +417,58 @@ export const getContainerLogs = async (
}
};
-export const containerRestart = async (containerId: string) => {
- try {
- const { stdout, stderr } = await execAsync(
- `docker container restart ${containerId}`,
- );
+export const containerRestart = async (
+ containerId: string,
+ serverId?: string,
+) => {
+ const command = `docker container restart ${containerId}`;
+ const { stderr } = serverId
+ ? await execAsyncRemote(serverId, command)
+ : await execAsync(command);
- if (stderr) {
- console.error(`Error: ${stderr}`);
- return;
- }
+ if (stderr) {
+ console.error(`Error: ${stderr}`);
+ throw new Error(stderr);
+ }
+};
- const config = JSON.parse(stdout);
+export const containerStart = async (
+ containerId: string,
+ serverId?: string,
+) => {
+ const command = `docker container start ${containerId}`;
+ const { stderr } = serverId
+ ? await execAsyncRemote(serverId, command)
+ : await execAsync(command);
- return config;
- } catch {}
+ if (stderr) {
+ console.error(`Error: ${stderr}`);
+ throw new Error(stderr);
+ }
+};
+
+export const containerStop = async (containerId: string, serverId?: string) => {
+ const command = `docker container stop ${containerId}`;
+ const { stderr } = serverId
+ ? await execAsyncRemote(serverId, command)
+ : await execAsync(command);
+
+ if (stderr) {
+ console.error(`Error: ${stderr}`);
+ throw new Error(stderr);
+ }
+};
+
+export const containerKill = async (containerId: string, serverId?: string) => {
+ const command = `docker container kill ${containerId}`;
+ const { stderr } = serverId
+ ? await execAsyncRemote(serverId, command)
+ : await execAsync(command);
+
+ if (stderr) {
+ console.error(`Error: ${stderr}`);
+ throw new Error(stderr);
+ }
};
export const containerRemove = async (