From 41d355c7dc7fd1d1945a1720e57c4cbc7d7e634a Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Tue, 18 Aug 2026 02:19:41 -0600 Subject: [PATCH] fix: use dockerode API instead of shell docker ps for changePassword container lookup Fixes #5108. The changePassword mutations for postgres/mysql/mariadb/mongo/redis detected the running container via a shell one-liner (docker ps -q --filter status=running | head -n1) executed through execAsync/execAsyncRemote. When that shell command failed for any reason the CONTAINER_ID ended up empty and the mutation incorrectly reported the container as not running even though it was. Replaced it with getServiceContainer(), the existing dockerode-based lookup already used by mount.ts and schedules/utils.ts for the same purpose. Also fixes the postgres ALTER USER command, which never selected a database and defaulted to a database named after the user, causing a false 'database "" does not exist' failure whenever the db name differs from the username. --- apps/dokploy/server/api/routers/mariadb.ts | 20 ++++++++++---------- apps/dokploy/server/api/routers/mongo.ts | 20 ++++++++++---------- apps/dokploy/server/api/routers/mysql.ts | 20 ++++++++++---------- apps/dokploy/server/api/routers/postgres.ts | 20 ++++++++++---------- apps/dokploy/server/api/routers/redis.ts | 20 ++++++++++---------- 5 files changed, 50 insertions(+), 50 deletions(-) diff --git a/apps/dokploy/server/api/routers/mariadb.ts b/apps/dokploy/server/api/routers/mariadb.ts index 4366e7393..98932f8af 100644 --- a/apps/dokploy/server/api/routers/mariadb.ts +++ b/apps/dokploy/server/api/routers/mariadb.ts @@ -11,7 +11,7 @@ import { findProjectById, getAccessibleServerIds, getContainerLogs, - getServiceContainerCommand, + getServiceContainer, getWebServerSettings, IS_CLOUD, rebuildDatabase, @@ -410,17 +410,17 @@ export const mariadbRouter = createTRPCRouter({ const maria = await findMariadbById(mariadbId); const { appName, serverId, databaseUser, databaseRootPassword } = maria; - const containerCmd = getServiceContainerCommand(appName); + const container = await getServiceContainer(appName, serverId); + if (!container) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: `No running container found for ${appName}`, + }); + } + const targetUser = type === "root" ? "root" : databaseUser; - const command = ` - CONTAINER_ID=$(${containerCmd}) - if [ -z "$CONTAINER_ID" ]; then - echo "No running container found for ${appName}" >&2 - exit 1 - fi - docker exec "$CONTAINER_ID" mariadb -u root -p'${databaseRootPassword}' -e "ALTER USER '${targetUser}'@'%' IDENTIFIED BY '${password}'; FLUSH PRIVILEGES;" - `; + const command = `docker exec ${container.Id} mariadb -u root -p'${databaseRootPassword}' -e "ALTER USER '${targetUser}'@'%' IDENTIFIED BY '${password}'; FLUSH PRIVILEGES;"`; await db.transaction(async (tx) => { const setData = diff --git a/apps/dokploy/server/api/routers/mongo.ts b/apps/dokploy/server/api/routers/mongo.ts index de38435b4..42b410785 100644 --- a/apps/dokploy/server/api/routers/mongo.ts +++ b/apps/dokploy/server/api/routers/mongo.ts @@ -11,7 +11,7 @@ import { findProjectById, getAccessibleServerIds, getContainerLogs, - getServiceContainerCommand, + getServiceContainer, getWebServerSettings, IS_CLOUD, rebuildDatabase, @@ -431,15 +431,15 @@ export const mongoRouter = createTRPCRouter({ const mongo = await findMongoById(mongoId); const { appName, serverId, databaseUser, databasePassword } = mongo; - const containerCmd = getServiceContainerCommand(appName); - const command = ` - CONTAINER_ID=$(${containerCmd}) - if [ -z "$CONTAINER_ID" ]; then - echo "No running container found for ${appName}" >&2 - exit 1 - fi - docker exec "$CONTAINER_ID" mongosh -u '${databaseUser}' -p '${databasePassword}' --authenticationDatabase admin --eval "db.getSiblingDB('admin').changeUserPassword('${databaseUser}', '${password}')" - `; + const container = await getServiceContainer(appName, serverId); + if (!container) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: `No running container found for ${appName}`, + }); + } + + const command = `docker exec ${container.Id} mongosh -u '${databaseUser}' -p '${databasePassword}' --authenticationDatabase admin --eval "db.getSiblingDB('admin').changeUserPassword('${databaseUser}', '${password}')"`; await db.transaction(async (tx) => { await tx diff --git a/apps/dokploy/server/api/routers/mysql.ts b/apps/dokploy/server/api/routers/mysql.ts index 70c40520a..c315ec5d4 100644 --- a/apps/dokploy/server/api/routers/mysql.ts +++ b/apps/dokploy/server/api/routers/mysql.ts @@ -11,7 +11,7 @@ import { findProjectById, getAccessibleServerIds, getContainerLogs, - getServiceContainerCommand, + getServiceContainer, getWebServerSettings, IS_CLOUD, rebuildDatabase, @@ -428,17 +428,17 @@ export const mysqlRouter = createTRPCRouter({ const my = await findMySqlById(mysqlId); const { appName, serverId, databaseUser, databaseRootPassword } = my; - const containerCmd = getServiceContainerCommand(appName); + const container = await getServiceContainer(appName, serverId); + if (!container) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: `No running container found for ${appName}`, + }); + } + const targetUser = type === "root" ? "root" : databaseUser; - const command = ` - CONTAINER_ID=$(${containerCmd}) - if [ -z "$CONTAINER_ID" ]; then - echo "No running container found for ${appName}" >&2 - exit 1 - fi - docker exec "$CONTAINER_ID" mysql -u root -p'${databaseRootPassword}' -e "ALTER USER '${targetUser}'@'%' IDENTIFIED BY '${password}'; FLUSH PRIVILEGES;" - `; + const command = `docker exec ${container.Id} mysql -u root -p'${databaseRootPassword}' -e "ALTER USER '${targetUser}'@'%' IDENTIFIED BY '${password}'; FLUSH PRIVILEGES;"`; await db.transaction(async (tx) => { const setData = diff --git a/apps/dokploy/server/api/routers/postgres.ts b/apps/dokploy/server/api/routers/postgres.ts index 9b1b3330a..97e398123 100644 --- a/apps/dokploy/server/api/routers/postgres.ts +++ b/apps/dokploy/server/api/routers/postgres.ts @@ -12,7 +12,7 @@ import { getAccessibleServerIds, getContainerLogs, getMountPath, - getServiceContainerCommand, + getServiceContainer, getWebServerSettings, IS_CLOUD, rebuildDatabase, @@ -437,15 +437,15 @@ export const postgresRouter = createTRPCRouter({ const pg = await findPostgresById(postgresId); const { appName, serverId, databaseUser } = pg; - const containerCmd = getServiceContainerCommand(appName); - const command = ` - CONTAINER_ID=$(${containerCmd}) - if [ -z "$CONTAINER_ID" ]; then - echo "No running container found for ${appName}" >&2 - exit 1 - fi - docker exec "$CONTAINER_ID" psql -U ${databaseUser} -c "ALTER USER \\"${databaseUser}\\" WITH PASSWORD '${password}';" - `; + const container = await getServiceContainer(appName, serverId); + if (!container) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: `No running container found for ${appName}`, + }); + } + + const command = `docker exec ${container.Id} psql -U ${databaseUser} -d postgres -c "ALTER USER \\"${databaseUser}\\" WITH PASSWORD '${password}';"`; await db.transaction(async (tx) => { await tx diff --git a/apps/dokploy/server/api/routers/redis.ts b/apps/dokploy/server/api/routers/redis.ts index 747cce4a3..fb0d8301c 100644 --- a/apps/dokploy/server/api/routers/redis.ts +++ b/apps/dokploy/server/api/routers/redis.ts @@ -10,7 +10,7 @@ import { findRedisById, getAccessibleServerIds, getContainerLogs, - getServiceContainerCommand, + getServiceContainer, getWebServerSettings, IS_CLOUD, rebuildDatabase, @@ -418,15 +418,15 @@ export const redisRouter = createTRPCRouter({ const rd = await findRedisById(redisId); const { appName, serverId, databasePassword } = rd; - const containerCmd = getServiceContainerCommand(appName); - const command = ` - CONTAINER_ID=$(${containerCmd}) - if [ -z "$CONTAINER_ID" ]; then - echo "No running container found for ${appName}" >&2 - exit 1 - fi - docker exec "$CONTAINER_ID" redis-cli -a '${databasePassword}' CONFIG SET requirepass '${password}' - `; + const container = await getServiceContainer(appName, serverId); + if (!container) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: `No running container found for ${appName}`, + }); + } + + const command = `docker exec ${container.Id} redis-cli -a '${databasePassword}' CONFIG SET requirepass '${password}'`; await db.transaction(async (tx) => { await tx