From 596f8bcf976265338e5946f75234494fd6e3f483 Mon Sep 17 00:00:00 2001 From: TheGenio Date: Mon, 2 Feb 2026 00:49:22 +0300 Subject: [PATCH 1/3] feat: add custom container name prefix option --- app/Livewire/Project/Application/Advanced.php | 23 +++++++++++++++ bootstrap/helpers/docker.php | 6 +++- ...er_name_prefix_to_application_settings.php | 28 +++++++++++++++++++ .../project/application/advanced.blade.php | 7 +++++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 database/migrations/2026_02_02_000000_add_custom_container_name_prefix_to_application_settings.php diff --git a/app/Livewire/Project/Application/Advanced.php b/app/Livewire/Project/Application/Advanced.php index cf7ef3e0b..75fe6fcfc 100644 --- a/app/Livewire/Project/Application/Advanced.php +++ b/app/Livewire/Project/Application/Advanced.php @@ -70,6 +70,9 @@ class Advanced extends Component #[Validate(['string', 'nullable'])] public ?string $customInternalName = null; + #[Validate(['string', 'nullable'])] + public ?string $customContainerNamePrefix = null; + #[Validate(['boolean'])] public bool $isGzipEnabled = true; @@ -111,6 +114,7 @@ class Advanced extends Component $this->application->settings->is_build_server_enabled = $this->isBuildServerEnabled; $this->application->settings->is_consistent_container_name_enabled = $this->isConsistentContainerNameEnabled; $this->application->settings->custom_internal_name = $this->customInternalName; + $this->application->settings->custom_container_name_prefix = $this->customContainerNamePrefix; $this->application->settings->is_gzip_enabled = $this->isGzipEnabled; $this->application->settings->is_stripprefix_enabled = $this->isStripprefixEnabled; $this->application->settings->is_raw_compose_deployment_enabled = $this->isRawComposeDeploymentEnabled; @@ -139,6 +143,7 @@ class Advanced extends Component $this->isBuildServerEnabled = $this->application->settings->is_build_server_enabled; $this->isConsistentContainerNameEnabled = $this->application->settings->is_consistent_container_name_enabled; $this->customInternalName = $this->application->settings->custom_internal_name; + $this->customContainerNamePrefix = $this->application->settings->custom_container_name_prefix; $this->isRawComposeDeploymentEnabled = $this->application->settings->is_raw_compose_deployment_enabled; $this->isConnectToDockerNetworkEnabled = $this->application->settings->connect_to_docker_network; $this->disableBuildCache = $this->application->settings->disable_build_cache; @@ -252,6 +257,24 @@ class Advanced extends Component } } + public function saveCustomNamePrefix() + { + try { + $this->authorize('update', $this->application); + + if (str($this->customContainerNamePrefix)->isNotEmpty()) { + $this->customContainerNamePrefix = str($this->customContainerNamePrefix)->slug()->value(); + } else { + $this->customContainerNamePrefix = null; + } + + $this->syncData(true); + $this->dispatch('success', 'Custom container name prefix saved.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function render() { return view('livewire.project.application.advanced'); diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index b0d401b5f..af7166e08 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -180,6 +180,7 @@ function generateApplicationContainerName(Application $application, $pull_reques // TODO: refactor generateApplicationContainerName, we do not need $application and $pull_request_id $consistent_container_name = $application->settings->is_consistent_container_name_enabled; + $custom_container_name_prefix = $application->settings->custom_container_name_prefix; $now = now()->format('Hisu'); if ($pull_request_id !== 0 && $pull_request_id !== null) { return $application->uuid.'-pr-'.$pull_request_id; @@ -188,7 +189,10 @@ function generateApplicationContainerName(Application $application, $pull_reques return $application->uuid; } - return $application->uuid.'-'.$now; + // Use custom prefix if set, otherwise use uuid + $prefix = $custom_container_name_prefix ?? $application->uuid; + + return $prefix.'-'.$now; } } function get_port_from_dockerfile($dockerfile): ?int diff --git a/database/migrations/2026_02_02_000000_add_custom_container_name_prefix_to_application_settings.php b/database/migrations/2026_02_02_000000_add_custom_container_name_prefix_to_application_settings.php new file mode 100644 index 000000000..bbeb825e2 --- /dev/null +++ b/database/migrations/2026_02_02_000000_add_custom_container_name_prefix_to_application_settings.php @@ -0,0 +1,28 @@ +string('custom_container_name_prefix')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('application_settings', function (Blueprint $table) { + $table->dropColumn('custom_container_name_prefix'); + }); + } +}; diff --git a/resources/views/livewire/project/application/advanced.blade.php b/resources/views/livewire/project/application/advanced.blade.php index 907500dfa..63656c34f 100644 --- a/resources/views/livewire/project/application/advanced.blade.php +++ b/resources/views/livewire/project/application/advanced.blade.php @@ -68,6 +68,13 @@ :canResource="$application" /> Save +
+ + Save + @endif @if ($application->build_pack === 'dockercompose')

Network

From a5599da8366a553812e3fe57322ea84608285b1a Mon Sep 17 00:00:00 2001 From: TheGenio Date: Mon, 2 Feb 2026 01:02:59 +0300 Subject: [PATCH 2/3] feat: add custom container name prefix option --- bootstrap/helpers/docker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index af7166e08..96c64dd6e 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -189,7 +189,7 @@ function generateApplicationContainerName(Application $application, $pull_reques return $application->uuid; } - // Use custom prefix if set, otherwise use uuid + $prefix = $custom_container_name_prefix ?? $application->uuid; return $prefix.'-'.$now; From dd2fe5a3ac8036740cd58ef2dcaec498cda50e52 Mon Sep 17 00:00:00 2001 From: TheGenio Date: Tue, 10 Feb 2026 00:06:22 +0300 Subject: [PATCH 3/3] feat: enhance custom container name handling with validation and UI updates --- app/Livewire/Project/Application/Advanced.php | 35 ++++++++++++++++++- .../project/application/advanced.blade.php | 17 +++++---- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/app/Livewire/Project/Application/Advanced.php b/app/Livewire/Project/Application/Advanced.php index 75fe6fcfc..bb1e58067 100644 --- a/app/Livewire/Project/Application/Advanced.php +++ b/app/Livewire/Project/Application/Advanced.php @@ -236,12 +236,19 @@ class Advanced extends Component return; } + + $this->customContainerNamePrefix = null; $customInternalName = $this->customInternalName; $server = $this->application->destination->server; $allApplications = $server->applications(); $foundSameInternalName = $allApplications->filter(function ($application) { - return $application->id !== $this->application->id && $application->settings->custom_internal_name === $this->customInternalName; + if ($application->id === $this->application->id) { + return false; + } + + return $application->settings->custom_internal_name === $this->customInternalName + || $application->settings->custom_container_name_prefix === $this->customInternalName; }); if ($foundSameInternalName->isNotEmpty()) { $this->dispatch('error', 'This custom container name is already in use by another application on this server.'); @@ -268,6 +275,32 @@ class Advanced extends Component $this->customContainerNamePrefix = null; } + if (is_null($this->customContainerNamePrefix)) { + $this->syncData(true); + $this->dispatch('success', 'Custom container name prefix saved.'); + + return; + } + + $this->customInternalName = null; + $server = $this->application->destination->server; + $allApplications = $server->applications(); + + $foundDuplicate = $allApplications->filter(function ($application) { + if ($application->id === $this->application->id) { + return false; + } + + return $application->settings->custom_container_name_prefix === $this->customContainerNamePrefix + || $application->settings->custom_internal_name === $this->customContainerNamePrefix; + }); + + if ($foundDuplicate->isNotEmpty()) { + $this->dispatch('error', 'This custom container name prefix is already in use by another application on this server.'); + + return; + } + $this->syncData(true); $this->dispatch('success', 'Custom container name prefix saved.'); } catch (\Throwable $e) { diff --git a/resources/views/livewire/project/application/advanced.blade.php b/resources/views/livewire/project/application/advanced.blade.php index 63656c34f..2c7e4d743 100644 --- a/resources/views/livewire/project/application/advanced.blade.php +++ b/resources/views/livewire/project/application/advanced.blade.php @@ -63,17 +63,20 @@ @if ($isConsistentContainerNameEnabled === false)
- Save + helper="You can add a custom name for your container.

The name will be converted to slug format when you save it. You will lose the rolling update feature!

Cannot be used together with Custom Container Name Prefix." + id="customInternalName" label="Custom Container Name" canGate="update" + :canResource="$application" :disabled="!empty($customContainerNamePrefix)" /> + Save
- Save + :canResource="$application" placeholder="e.g. my-nextjs-app" + :disabled="!empty($customInternalName)" /> + Save @endif @if ($application->build_pack === 'dockercompose')