mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
Merge pull request #4065 from Dokploy/2779-implement-removing-unsuedexited-containers
feat(docker): implement container removal functionality
This commit is contained in:
@@ -0,0 +1,66 @@
|
|||||||
|
import { toast } from "sonner";
|
||||||
|
import {
|
||||||
|
AlertDialog,
|
||||||
|
AlertDialogAction,
|
||||||
|
AlertDialogCancel,
|
||||||
|
AlertDialogContent,
|
||||||
|
AlertDialogDescription,
|
||||||
|
AlertDialogFooter,
|
||||||
|
AlertDialogHeader,
|
||||||
|
AlertDialogTitle,
|
||||||
|
AlertDialogTrigger,
|
||||||
|
} from "@/components/ui/alert-dialog";
|
||||||
|
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
containerId: string;
|
||||||
|
serverId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RemoveContainerDialog = ({ containerId, serverId }: Props) => {
|
||||||
|
const utils = api.useUtils();
|
||||||
|
const { mutateAsync, isPending } = api.docker.removeContainer.useMutation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AlertDialog>
|
||||||
|
<AlertDialogTrigger asChild>
|
||||||
|
<DropdownMenuItem
|
||||||
|
className="w-full cursor-pointer text-red-500 hover:!text-red-600"
|
||||||
|
onSelect={(e) => e.preventDefault()}
|
||||||
|
>
|
||||||
|
Remove Container
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</AlertDialogTrigger>
|
||||||
|
<AlertDialogContent>
|
||||||
|
<AlertDialogHeader>
|
||||||
|
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
|
||||||
|
<AlertDialogDescription>
|
||||||
|
This will permanently remove the container{" "}
|
||||||
|
<span className="font-semibold">{containerId}</span>. If the
|
||||||
|
container is running, it will be forcefully stopped and removed.
|
||||||
|
This action cannot be undone.
|
||||||
|
</AlertDialogDescription>
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogFooter>
|
||||||
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||||
|
<AlertDialogAction
|
||||||
|
disabled={isPending}
|
||||||
|
onClick={async () => {
|
||||||
|
await mutateAsync({ containerId, serverId })
|
||||||
|
.then(async () => {
|
||||||
|
toast.success("Container removed successfully");
|
||||||
|
await utils.docker.getContainers.invalidate();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
toast.error(err.message);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Confirm
|
||||||
|
</AlertDialogAction>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import { ShowContainerConfig } from "../config/show-container-config";
|
import { ShowContainerConfig } from "../config/show-container-config";
|
||||||
import { ShowDockerModalLogs } from "../logs/show-docker-modal-logs";
|
import { ShowDockerModalLogs } from "../logs/show-docker-modal-logs";
|
||||||
|
import { RemoveContainerDialog } from "../remove/remove-container";
|
||||||
import { DockerTerminalModal } from "../terminal/docker-terminal-modal";
|
import { DockerTerminalModal } from "../terminal/docker-terminal-modal";
|
||||||
import type { Container } from "./show-containers";
|
import type { Container } from "./show-containers";
|
||||||
|
|
||||||
@@ -127,6 +128,10 @@ export const columns: ColumnDef<Container>[] = [
|
|||||||
>
|
>
|
||||||
Terminal
|
Terminal
|
||||||
</DockerTerminalModal>
|
</DockerTerminalModal>
|
||||||
|
<RemoveContainerDialog
|
||||||
|
containerId={container.containerId}
|
||||||
|
serverId={container.serverId}
|
||||||
|
/>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
containerRemove,
|
||||||
containerRestart,
|
containerRestart,
|
||||||
findServerById,
|
findServerById,
|
||||||
getConfig,
|
getConfig,
|
||||||
@@ -52,6 +53,32 @@ export const dockerRouter = createTRPCRouter({
|
|||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
removeContainer: withPermission("docker", "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 containerRemove(input.containerId, input.serverId);
|
||||||
|
await audit(ctx, {
|
||||||
|
action: "delete",
|
||||||
|
resourceType: "docker",
|
||||||
|
resourceId: input.containerId,
|
||||||
|
resourceName: input.containerId,
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
getConfig: withPermission("docker", "read")
|
getConfig: withPermission("docker", "read")
|
||||||
.input(
|
.input(
|
||||||
z.object({
|
z.object({
|
||||||
|
|||||||
@@ -371,6 +371,21 @@ export const containerRestart = async (containerId: string) => {
|
|||||||
} catch {}
|
} catch {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const containerRemove = async (
|
||||||
|
containerId: string,
|
||||||
|
serverId?: string,
|
||||||
|
) => {
|
||||||
|
const command = `docker rm -f ${containerId}`;
|
||||||
|
const { stderr } = serverId
|
||||||
|
? await execAsyncRemote(serverId, command)
|
||||||
|
: await execAsync(command);
|
||||||
|
|
||||||
|
if (stderr) {
|
||||||
|
console.error(`Error: ${stderr}`);
|
||||||
|
throw new Error(stderr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const getSwarmNodes = async (serverId?: string) => {
|
export const getSwarmNodes = async (serverId?: string) => {
|
||||||
try {
|
try {
|
||||||
let stdout = "";
|
let stdout = "";
|
||||||
|
|||||||
Reference in New Issue
Block a user