diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index bab7925c0..10bb9a0f8 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -363,7 +363,9 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue $this->server = $this->build_server; } $dockerfile_base64 = base64_encode($this->application->dockerfile); + $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->application->name} to {$this->server->name}."); + $didLogin = $this->handleRegistryAuth(); $this->prepare_builder_image(); $this->execute_remote_command( [ @@ -382,12 +384,24 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue private function deploy_dockerimage_buildpack() { try { + // setup + $this->dockerImage = $this->application->docker_registry_image_name; + if (str($this->application->docker_registry_image_tag)->isEmpty()) { + $this->dockerImageTag = 'latest'; + } else { + $this->dockerImageTag = $this->application->docker_registry_image_tag; + } + + $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->dockerImage}:{$this->dockerImageTag} to {$this->server->name}."); + // login $didLogin = $this->handleRegistryAuth(); - // Pull the image - $this->execute_remote_command([ - "docker pull {$this->application->image}", - ]); + $this->generate_image_names(); + $this->prepare_builder_image(); + $this->generate_compose_file(); + $this->rolling_update(); + + // Logout if we logged in if ($didLogin) { @@ -591,6 +605,8 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue private function deploy_dockerfile_buildpack() { + // login + $didLogin = $this->handleRegistryAuth(); $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->customRepository}:{$this->application->git_branch} to {$this->server->name}."); if ($this->use_build_server) { $this->server = $this->build_server; @@ -1970,7 +1986,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue $this->application_deployment_queue->addLogEntry("Pulling latest image ($image) from the registry."); $this->execute_remote_command( [ - executeInDocker($this->deployment_uuid, "docker pull {$image}"), + executeInDocker($this->deployment_uuid, "docker pull {$this->application->registry_url}/{$image}"), 'hidden' => true, ] ); @@ -2464,27 +2480,31 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); } private function handleRegistryAuth() -{ - if ($this->application->registry_username && $this->application->registry_token) { - try { - $username = escapeshellarg($this->application->registry_username); - $token = escapeshellarg(decrypt($this->application->registry_token)); + { + if ($this->application->docker_use_custom_registry) { + try { + $username = escapeshellarg($this->application->docker_registry_username); + $token = escapeshellarg(decrypt($this->application->docker_registry_token)); + + $registry = $this->application->docker_registry_url ?: 'docker.io'; // Default to docker.io + $registry = escapeshellarg($registry); - $this->application_deployment_queue->addLogEntry('Attempting to log into registry...'); + $this->application_deployment_queue->addLogEntry('Attempting to log into registry...'); - $command = "echo {$token} | docker login -u {$username} --password-stdin > /dev/null"; + $command = "echo {$token} | docker login {$registry} -u {$username} --password-stdin"; + $this->application_deployment_queue->addLogEntry($command); - $this->execute_remote_command([ + $this->execute_remote_command([ $command, 'hidden' => true, - ]); - - return true; - } catch (Exception $e) { - $this->application_deployment_queue->addLogEntry('Registry authentication error: ' . $e->getMessage(), 'stderr'); - throw $e; + ]); + + return true; + } catch (Exception $e) { + $this->application_deployment_queue->addLogEntry('Registry authentication error: ' . $e->getMessage(), 'stderr'); + throw $e; + } } + return false; } - return false; -} } diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php index f1575a01f..4ad57d2a7 100644 --- a/app/Livewire/Project/Application/General.php +++ b/app/Livewire/Project/Application/General.php @@ -71,6 +71,10 @@ class General extends Component 'application.dockerfile' => 'nullable', 'application.docker_registry_image_name' => 'nullable', 'application.docker_registry_image_tag' => 'nullable', + 'application.docker_use_custom_registry' => 'boolean', + 'application.docker_registry_url' => 'nullable', + 'application.docker_registry_username' => 'required_with:application.docker_use_custom_registry', + 'application.docker_registry_token' => 'required_with:application.docker_use_custom_registry', 'application.dockerfile_location' => 'nullable', 'application.docker_compose_location' => 'nullable', 'application.docker_compose' => 'nullable', @@ -112,6 +116,10 @@ class General extends Component 'application.dockerfile' => 'Dockerfile', 'application.docker_registry_image_name' => 'Docker registry image name', 'application.docker_registry_image_tag' => 'Docker registry image tag', + 'application.docker_use_custom_registry' => 'Docker use custom registry', + 'application.docker_registry_url' => 'Registry URL', + 'application.docker_registry_username' => 'Registry Username', + 'application.docker_registry_token' => 'Registry Token', 'application.dockerfile_location' => 'Dockerfile location', 'application.docker_compose_location' => 'Docker compose location', 'application.docker_compose' => 'Docker compose', diff --git a/app/Livewire/Project/New/DockerImage.php b/app/Livewire/Project/New/DockerImage.php index af7c62dd8..e201c203d 100644 --- a/app/Livewire/Project/New/DockerImage.php +++ b/app/Livewire/Project/New/DockerImage.php @@ -14,29 +14,41 @@ class DockerImage extends Component public string $dockerImage = ''; public ?string $registryUsername = null; public ?string $registryToken = null; + public ?string $registryUrl = 'docker.io'; + public bool $useCustomRegistry = false; public array $parameters; public array $query; protected $rules = [ 'dockerImage' => 'required|string', - 'registryUsername' => 'nullable|string', - 'registryToken' => 'nullable|string', + 'registryUsername' => 'required_with:useCustomRegistry|string', + 'registryToken' => 'required_with:useCustomRegistry|string', + 'registryUrl' => 'nullable|string', + 'useCustomRegistry' => 'boolean' ]; public function mount() { $this->parameters = get_route_parameters(); $this->query = request()->query(); + $this->registryUrl = 'docker.io'; } public function submit() { $this->validate([ 'dockerImage' => 'required', - 'registryUsername' => 'required_with:registryToken', - 'registryToken' => 'required_with:registryUsername', + 'registryUsername' => 'required_with:useCustomRegistry', + 'registryToken' => 'required_with:useCustomRegistry', ]); + // Only save registry settings if useCustomRegistry is true + if (!$this->useCustomRegistry) { + $this->registryUsername = null; + $this->registryToken = null; + $this->registryUrl = 'docker.io'; + } + $image = str($this->dockerImage)->before(':'); $tag = str($this->dockerImage)->contains(':') ? str($this->dockerImage)->after(':') : @@ -70,8 +82,10 @@ class DockerImage extends Component 'destination_id' => $destination->id, 'destination_type' => $destination_class, 'health_check_enabled' => false, - 'registry_username' => $this->registryUsername, - 'registry_token' => $this->registryToken ? encrypt($this->registryToken) : null, + 'docker_use_custom_registry' => $this->useCustomRegistry, + 'docker_registry_url' => $this->registryUrl, + 'docker_registry_username' => $this->registryUsername, + 'docker_registry_token' => $this->registryToken ? encrypt($this->registryToken) : null, ]); $fqdn = generateFqdn($destination->server, $application->uuid); diff --git a/app/Models/Application.php b/app/Models/Application.php index 0ef787b2e..2180b78a3 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -35,6 +35,10 @@ use Visus\Cuid2\Cuid2; 'git_full_url' => ['type' => 'string', 'nullable' => true, 'description' => 'Git full URL.'], 'docker_registry_image_name' => ['type' => 'string', 'nullable' => true, 'description' => 'Docker registry image name.'], 'docker_registry_image_tag' => ['type' => 'string', 'nullable' => true, 'description' => 'Docker registry image tag.'], + 'docker_use_custom_registry' => ['type' => 'boolean', 'description' => 'Use custom registry.'], + 'docker_registry_url' => ['type' => 'string', 'nullable' => true, 'description' => 'Registry URL.'], + 'docker_registry_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Registry username.'], + 'docker_registry_token' => ['type' => 'string', 'nullable' => true, 'description' => 'Registry token.'], 'build_pack' => ['type' => 'string', 'description' => 'Build pack.', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose']], 'static_image' => ['type' => 'string', 'description' => 'Static image used when static site is deployed.'], 'install_command' => ['type' => 'string', 'description' => 'Install command.'], diff --git a/database/migrations/2024_11_08_084443_add_registry_auth_to_applications_table.php b/database/migrations/2024_11_08_084443_add_registry_auth_to_applications_table.php index d3800b4a9..422503bfc 100644 --- a/database/migrations/2024_11_08_084443_add_registry_auth_to_applications_table.php +++ b/database/migrations/2024_11_08_084443_add_registry_auth_to_applications_table.php @@ -8,16 +8,20 @@ return new class extends Migration { public function up(): void { Schema::table('applications', function (Blueprint $table) { - $table->string('registry_username')->nullable(); - $table->text('registry_token')->nullable(); + $table->string('docker_registry_username')->nullable(); + $table->text('docker_registry_token')->nullable(); + $table->string('docker_registry_url')->nullable(); + $table->boolean('docker_use_custom_registry')->default(false); }); } public function down(): void { Schema::table('applications', function (Blueprint $table) { - $table->dropColumn('registry_username'); - $table->dropColumn('registry_token'); + $table->dropColumn('docker_registry_username'); + $table->dropColumn('docker_registry_token'); + $table->dropColumn('docker_registry_url'); + $table->dropColumn('docker_use_custom_registry'); }); } }; \ No newline at end of file diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index ed50fd230..2fa49c059 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -101,34 +101,56 @@ target="_blank">here. @endif @endif -
- @if ($application->build_pack === 'dockerimage') - @if ($application->destination->server->isSwarm()) - - +
+
+ @if ($application->build_pack === 'dockerimage') + @if ($application->destination->server->isSwarm()) + + + @else + + + @endif @else - - + @if ( + $application->destination->server->isSwarm() || + $application->additional_servers->count() > 0 || + $application->settings->is_build_server_enabled) + + + @else + + + @endif @endif - @else - @if ( - $application->destination->server->isSwarm() || - $application->additional_servers->count() > 0 || - $application->settings->is_build_server_enabled) - - - @else - - +
+ + @if ($application->build_pack === 'dockerimage') +
+ +
+ + @if ($application->docker_use_custom_registry) +
+ + + +
@endif @endif
diff --git a/resources/views/livewire/project/new/docker-image.blade.php b/resources/views/livewire/project/new/docker-image.blade.php index 5bc7df060..c1bbbb1d9 100644 --- a/resources/views/livewire/project/new/docker-image.blade.php +++ b/resources/views/livewire/project/new/docker-image.blade.php @@ -8,16 +8,25 @@
-

Registry Authentication

-
- - - +
+
+ + @if ($useCustomRegistry) +

Registry Authentication

+
+ + + + + +
+ @endif