From 6a10923a505db2669b6faad78bfb0b4effde83d3 Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Fri, 7 Aug 2026 01:34:15 -0600 Subject: [PATCH] fix: warn when the postgres image implies a data directory that mismatches the mounted volume --- .../postgres/advanced/show-custom-command.tsx | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/apps/dokploy/components/dashboard/postgres/advanced/show-custom-command.tsx b/apps/dokploy/components/dashboard/postgres/advanced/show-custom-command.tsx index 07e059ce8d..5a1a7753d2 100644 --- a/apps/dokploy/components/dashboard/postgres/advanced/show-custom-command.tsx +++ b/apps/dokploy/components/dashboard/postgres/advanced/show-custom-command.tsx @@ -4,6 +4,7 @@ import { useEffect } from "react"; import { useFieldArray, useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; +import { AlertBlock } from "@/components/shared/alert-block"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { @@ -18,6 +19,19 @@ import { Input } from "@/components/ui/input"; import { api } from "@/utils/api"; import type { ServiceType } from "../../application/advanced/show-resources"; +const getPostgresMountPath = (dockerImage: string): string => { + const versionMatch = dockerImage.match(/postgres:(\d+)/); + if (versionMatch?.[1]) { + const version = Number.parseInt(versionMatch[1], 10); + if (version >= 18) { + return `/var/lib/postgresql/${version}/docker`; + } + } + return "/var/lib/postgresql/data"; +}; + +const POSTGRES_DATA_PATH_REGEX = /^\/var\/lib\/postgresql(\/|$)/; + const addDockerImage = z.object({ dockerImage: z.string().min(1, "Docker image is required"), command: z.string(), @@ -91,6 +105,22 @@ export const ShowCustomCommand = ({ id, type }: Props) => { } }, [data, form]); + const dockerImage = form.watch("dockerImage"); + + const mountPathWarning = (() => { + if (type !== "postgres" || !dockerImage) return null; + const mounts = (data as any)?.mounts ?? []; + const dataMount = mounts.find( + (mount: { type: string; mountPath: string }) => + mount.type === "volume" && + POSTGRES_DATA_PATH_REGEX.test(mount.mountPath), + ); + if (!dataMount) return null; + const expectedPath = getPostgresMountPath(dockerImage); + if (expectedPath === dataMount.mountPath) return null; + return { expectedPath, currentPath: dataMount.mountPath }; + })(); + const onSubmit = async (formData: AddDockerImage) => { await mutateAsync({ mongoId: id || "", @@ -139,6 +169,18 @@ export const ShowCustomCommand = ({ id, type }: Props) => { )} /> + {mountPathWarning && ( + + This image expects its data directory under{" "} + {mountPathWarning.expectedPath}, but the + volume of this database is mounted at{" "} + {mountPathWarning.currentPath}. Changing the + image does not migrate existing data — Postgres may + crash-loop or start with an empty database. Adjust the + volume mount path in the Volumes section or keep a + compatible image before saving. + + )}