From 8d280b4aac3f6e0b6ec1de37335a1440043e1933 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Mon, 13 Oct 2025 10:01:54 +0200 Subject: [PATCH] fix: prevent container name conflict when updating database port mappings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When port mappings are changed in the UI and the database is restarted, the system now gracefully stops and removes the existing container before recreating it with the new configuration. This prevents the "container name already in use" error that occurred when Docker Compose tried to create a container with the same name but different port configuration. Changes: - Add graceful container stop (10s timeout) before docker compose up - Remove old container to avoid name conflicts - Use --timeout flag (modern Docker CLI) instead of deprecated --time - Apply fix to all database types: MariaDB, MySQL, PostgreSQL, MongoDB, Redis, KeyDB, Dragonfly, and ClickHouse - Update StopDatabase.php for consistency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/Actions/Database/StartClickhouse.php | 2 ++ app/Actions/Database/StartDragonfly.php | 2 ++ app/Actions/Database/StartKeydb.php | 2 ++ app/Actions/Database/StartMariadb.php | 2 ++ app/Actions/Database/StartMongodb.php | 2 ++ app/Actions/Database/StartMysql.php | 2 ++ app/Actions/Database/StartPostgresql.php | 2 ++ app/Actions/Database/StartRedis.php | 2 ++ app/Actions/Database/StopDatabase.php | 2 +- 9 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/Actions/Database/StartClickhouse.php b/app/Actions/Database/StartClickhouse.php index f218fcabb..38f6d7bc8 100644 --- a/app/Actions/Database/StartClickhouse.php +++ b/app/Actions/Database/StartClickhouse.php @@ -105,6 +105,8 @@ public function handle(StandaloneClickhouse $database) $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; + $this->commands[] = "docker stop --timeout=10 $container_name 2>/dev/null || true"; + $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "echo 'Database started.'"; diff --git a/app/Actions/Database/StartDragonfly.php b/app/Actions/Database/StartDragonfly.php index 0db73ba07..300221d24 100644 --- a/app/Actions/Database/StartDragonfly.php +++ b/app/Actions/Database/StartDragonfly.php @@ -192,6 +192,8 @@ public function handle(StandaloneDragonfly $database) if ($this->database->enable_ssl) { $this->commands[] = "chown -R 999:999 $this->configuration_dir/ssl/server.key $this->configuration_dir/ssl/server.crt"; } + $this->commands[] = "docker stop --timeout=10 $container_name 2>/dev/null || true"; + $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "echo 'Database started.'"; diff --git a/app/Actions/Database/StartKeydb.php b/app/Actions/Database/StartKeydb.php index 2908eb9c1..3a2ceebb3 100644 --- a/app/Actions/Database/StartKeydb.php +++ b/app/Actions/Database/StartKeydb.php @@ -208,6 +208,8 @@ public function handle(StandaloneKeydb $database) if ($this->database->enable_ssl) { $this->commands[] = "chown -R 999:999 $this->configuration_dir/ssl/server.key $this->configuration_dir/ssl/server.crt"; } + $this->commands[] = "docker stop --timeout=10 $container_name 2>/dev/null || true"; + $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "echo 'Database started.'"; diff --git a/app/Actions/Database/StartMariadb.php b/app/Actions/Database/StartMariadb.php index 11b424ff8..8a936c8ae 100644 --- a/app/Actions/Database/StartMariadb.php +++ b/app/Actions/Database/StartMariadb.php @@ -209,6 +209,8 @@ public function handle(StandaloneMariadb $database) $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; + $this->commands[] = "docker stop --timeout=10 $container_name 2>/dev/null || true"; + $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "echo 'Database started.'"; if ($this->database->enable_ssl) { diff --git a/app/Actions/Database/StartMongodb.php b/app/Actions/Database/StartMongodb.php index 0bf6ab253..19699d684 100644 --- a/app/Actions/Database/StartMongodb.php +++ b/app/Actions/Database/StartMongodb.php @@ -260,6 +260,8 @@ public function handle(StandaloneMongodb $database) $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; + $this->commands[] = "docker stop --timeout=10 $container_name 2>/dev/null || true"; + $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; if ($this->database->enable_ssl) { $this->commands[] = executeInDocker($this->database->uuid, 'chown mongodb:mongodb /etc/mongo/certs/server.pem'); diff --git a/app/Actions/Database/StartMysql.php b/app/Actions/Database/StartMysql.php index bf81d01ab..25546fa9d 100644 --- a/app/Actions/Database/StartMysql.php +++ b/app/Actions/Database/StartMysql.php @@ -210,6 +210,8 @@ public function handle(StandaloneMysql $database) $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; + $this->commands[] = "docker stop --timeout=10 $container_name 2>/dev/null || true"; + $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; if ($this->database->enable_ssl) { diff --git a/app/Actions/Database/StartPostgresql.php b/app/Actions/Database/StartPostgresql.php index 6cdf32e27..ac011acbe 100644 --- a/app/Actions/Database/StartPostgresql.php +++ b/app/Actions/Database/StartPostgresql.php @@ -223,6 +223,8 @@ public function handle(StandalonePostgresql $database) $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; + $this->commands[] = "docker stop --timeout=10 $container_name 2>/dev/null || true"; + $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; if ($this->database->enable_ssl) { $this->commands[] = executeInDocker($this->database->uuid, "chown {$this->database->postgres_user}:{$this->database->postgres_user} /var/lib/postgresql/certs/server.key /var/lib/postgresql/certs/server.crt"); diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index c040ec391..8a7ae42a4 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -205,6 +205,8 @@ public function handle(StandaloneRedis $database) if ($this->database->enable_ssl) { $this->commands[] = "chown -R 999:999 $this->configuration_dir/ssl/server.key $this->configuration_dir/ssl/server.crt"; } + $this->commands[] = "docker stop --timeout=10 $container_name 2>/dev/null || true"; + $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "echo 'Database started.'"; diff --git a/app/Actions/Database/StopDatabase.php b/app/Actions/Database/StopDatabase.php index 5c881e743..63f5b1979 100644 --- a/app/Actions/Database/StopDatabase.php +++ b/app/Actions/Database/StopDatabase.php @@ -49,7 +49,7 @@ private function stopContainer($database, string $containerName, int $timeout = { $server = $database->destination->server; instant_remote_process(command: [ - "docker stop --time=$timeout $containerName", + "docker stop --timeout=$timeout $containerName", "docker rm -f $containerName", ], server: $server, throwError: false); }