diff --git a/app/Http/Livewire/Dev/ScheduledBackups.php b/app/Http/Livewire/Dev/ScheduledBackups.php
deleted file mode 100644
index a7599d44a..000000000
--- a/app/Http/Livewire/Dev/ScheduledBackups.php
+++ /dev/null
@@ -1,16 +0,0 @@
-scheduledDatabaseBackup = ScheduledDatabaseBackup::all();
- }
-}
diff --git a/app/Http/Livewire/Project/Application/General.php b/app/Http/Livewire/Project/Application/General.php
index 53416ae00..8b2ed8900 100644
--- a/app/Http/Livewire/Project/Application/General.php
+++ b/app/Http/Livewire/Project/Application/General.php
@@ -47,6 +47,7 @@ class General extends Component
'application.publish_directory' => 'nullable',
'application.ports_exposes' => 'required',
'application.ports_mappings' => 'nullable',
+ 'application.dockerfile' => 'nullable',
];
protected $validationAttributes = [
'application.name' => 'name',
@@ -64,6 +65,7 @@ class General extends Component
'application.publish_directory' => 'Publish directory',
'application.ports_exposes' => 'Ports exposes',
'application.ports_mappings' => 'Ports mappings',
+ 'application.dockerfile' => 'Dockerfile',
];
public function instantSave()
@@ -140,6 +142,10 @@ public function submit()
$domains = Str::of($this->application->fqdn)->trim()->explode(',')->map(function ($domain) {
return Str::of($domain)->trim()->lower();
});
+ $port = get_port_from_dockerfile($this->application->dockerfile);
+ if ($port) {
+ $this->application->ports_exposes = $port;
+ }
if ($this->application->base_directory && $this->application->base_directory !== '/') {
$this->application->base_directory = rtrim($this->application->base_directory, '/');
}
diff --git a/app/Http/Livewire/Project/New/SimpleDockerfile.php b/app/Http/Livewire/Project/New/SimpleDockerfile.php
new file mode 100644
index 000000000..bbc82fcd5
--- /dev/null
+++ b/app/Http/Livewire/Project/New/SimpleDockerfile.php
@@ -0,0 +1,68 @@
+parameters = get_route_parameters();
+ $this->query = request()->query();
+ if (is_dev()) {
+ $this->dockerfile = 'FROM nginx
+EXPOSE 80
+CMD ["nginx", "-g", "daemon off;"]
+';
+ }
+ }
+ public function submit()
+ {
+ $this->validate([
+ 'dockerfile' => 'required'
+ ]);
+ $destination_uuid = $this->query['destination'];
+ $destination = StandaloneDocker::where('uuid', $destination_uuid)->first();
+ if (!$destination) {
+ $destination = SwarmDocker::where('uuid', $destination_uuid)->first();
+ }
+ if (!$destination) {
+ throw new \Exception('Destination not found. What?!');
+ }
+ $destination_class = $destination->getMorphClass();
+
+ $project = Project::where('uuid', $this->parameters['project_uuid'])->first();
+ $environment = $project->load(['environments'])->environments->where('name', $this->parameters['environment_name'])->first();
+
+ $port = get_port_from_dockerfile($this->dockerfile);
+ $application = Application::create([
+ 'name' => 'dockerfile-' . new Cuid2(7),
+ 'repository_project_id' => 0,
+ 'git_repository' => "coollabsio/coolify",
+ 'git_branch' => 'main',
+ 'build_pack' => 'dockerfile',
+ 'dockerfile' => $this->dockerfile,
+ 'ports_exposes' => $port,
+ 'environment_id' => $environment->id,
+ 'destination_id' => $destination->id,
+ 'destination_type' => $destination_class,
+ 'source_id' => 0,
+ 'source_type' => GithubApp::class
+ ]);
+ redirect()->route('project.application.configuration', [
+ 'application_uuid' => $application->uuid,
+ 'environment_name' => $environment->name,
+ 'project_uuid' => $project->uuid,
+ ]);
+ }
+}
diff --git a/app/Http/Livewire/Project/Shared/EnvironmentVariable/Show.php b/app/Http/Livewire/Project/Shared/EnvironmentVariable/Show.php
index f75a91b63..cfc94af22 100644
--- a/app/Http/Livewire/Project/Shared/EnvironmentVariable/Show.php
+++ b/app/Http/Livewire/Project/Shared/EnvironmentVariable/Show.php
@@ -28,6 +28,10 @@ public function mount()
$this->parameters = get_route_parameters();
}
+ public function instantSave()
+ {
+ $this->submit();
+ }
public function submit()
{
$this->validate();
diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php
index a37b609c7..fc0a3a1b7 100644
--- a/app/Jobs/ApplicationDeploymentJob.php
+++ b/app/Jobs/ApplicationDeploymentJob.php
@@ -117,10 +117,14 @@ public function handle(): void
'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
]);
try {
- if ($this->pull_request_id !== 0) {
- $this->deploy_pull_request();
+ if ($this->application->dockerfile) {
+ $this->deploy_simple_dockerfile();
} else {
- $this->deploy();
+ if ($this->pull_request_id !== 0) {
+ $this->deploy_pull_request();
+ } else {
+ $this->deploy();
+ }
}
if ($this->application->fqdn) dispatch(new ProxyStartJob($this->server));
$this->next(ApplicationDeploymentStatus::FINISHED->value);
@@ -150,7 +154,74 @@ public function handle(): void
);
}
}
+ private function deploy_simple_dockerfile()
+ {
+ $dockerfile_base64 = base64_encode($this->application->dockerfile);
+ $this->execute_remote_command(
+ [
+ "echo 'Starting deployment of {$this->application->name}.'"
+ ],
+ );
+ $this->prepare_builder_image();
+ $this->execute_remote_command(
+ [
+ $this->execute_in_builder("echo '$dockerfile_base64' | base64 -d > $this->workdir/Dockerfile")
+ ],
+ );
+ $this->build_image_name = "{$this->application->git_repository}:build";
+ $this->production_image_name = "{$this->application->uuid}:latest";
+ ray('Build Image Name: ' . $this->build_image_name . ' & Production Image Name: ' . $this->production_image_name)->green();
+ $this->generate_compose_file();
+ $this->generate_build_env_variables();
+ $this->add_build_env_variables_to_dockerfile();
+ $this->build_image();
+ $this->stop_running_container();
+ $this->start_by_compose_file();
+ }
+ private function deploy()
+ {
+ $this->execute_remote_command(
+ [
+ "echo 'Starting deployment of {$this->application->git_repository}:{$this->application->git_branch}.'"
+ ],
+ );
+ $this->prepare_builder_image();
+ $this->clone_repository();
+ $tag = Str::of("{$this->commit}-{$this->application->id}-{$this->pull_request_id}");
+ if (strlen($tag) > 128) {
+ $tag = $tag->substr(0, 128);
+ }
+
+ $this->build_image_name = "{$this->application->git_repository}:{$tag}-build";
+ $this->production_image_name = "{$this->application->uuid}:{$tag}";
+ ray('Build Image Name: ' . $this->build_image_name . ' & Production Image Name: ' . $this->production_image_name)->green();
+
+ if (!$this->force_rebuild) {
+ $this->execute_remote_command([
+ "docker images -q {$this->production_image_name} 2>/dev/null", "hidden" => true, "save" => "local_image_found"
+ ]);
+ if (Str::of($this->saved_outputs->get('local_image_found'))->isNotEmpty()) {
+ $this->execute_remote_command([
+ "echo 'Docker Image found locally with the same Git Commit SHA {$this->application->uuid}:{$this->commit}. Build step skipped...'"
+ ]);
+ $this->generate_compose_file();
+ $this->stop_running_container();
+ $this->start_by_compose_file();
+ return;
+ }
+ }
+ $this->cleanup_git();
+ if ($this->application->build_pack === 'nixpacks') {
+ $this->generate_nixpacks_confs();
+ }
+ $this->generate_compose_file();
+ $this->generate_build_env_variables();
+ $this->add_build_env_variables_to_dockerfile();
+ $this->build_image();
+ $this->stop_running_container();
+ $this->start_by_compose_file();
+ }
private function deploy_pull_request()
{
$this->build_image_name = "{$this->application->uuid}:pr-{$this->pull_request_id}-build";
@@ -162,7 +233,9 @@ private function deploy_pull_request()
$this->prepare_builder_image();
$this->clone_repository();
$this->cleanup_git();
- $this->generate_buildpack();
+ if ($this->application->build_pack === 'nixpacks') {
+ $this->generate_nixpacks_confs();
+ }
$this->generate_compose_file();
// Needs separate preview variables
// $this->generate_build_env_variables();
@@ -277,7 +350,7 @@ private function cleanup_git()
);
}
- private function generate_buildpack()
+ private function generate_nixpacks_confs()
{
$this->execute_remote_command(
[
@@ -589,49 +662,7 @@ private function start_by_compose_file()
);
}
- private function deploy()
- {
- $this->execute_remote_command(
- [
- "echo 'Starting deployment of {$this->application->git_repository}:{$this->application->git_branch}.'"
- ],
- );
- $this->prepare_builder_image();
- $this->clone_repository();
-
- $tag = Str::of("{$this->commit}-{$this->application->id}-{$this->pull_request_id}");
- if (strlen($tag) > 128) {
- $tag = $tag->substr(0, 128);
- }
-
- $this->build_image_name = "{$this->application->git_repository}:{$tag}-build";
- $this->production_image_name = "{$this->application->uuid}:{$tag}";
- ray('Build Image Name: ' . $this->build_image_name . ' & Production Image Name: ' . $this->production_image_name)->green();
-
- if (!$this->force_rebuild) {
- $this->execute_remote_command([
- "docker images -q {$this->production_image_name} 2>/dev/null", "hidden" => true, "save" => "local_image_found"
- ]);
- if (Str::of($this->saved_outputs->get('local_image_found'))->isNotEmpty()) {
- $this->execute_remote_command([
- "echo 'Docker Image found locally with the same Git Commit SHA {$this->application->uuid}:{$this->commit}. Build step skipped...'"
- ]);
- $this->generate_compose_file();
- $this->stop_running_container();
- $this->start_by_compose_file();
- return;
- }
- }
- $this->cleanup_git();
- $this->generate_buildpack();
- $this->generate_compose_file();
- $this->generate_build_env_variables();
- $this->add_build_env_variables_to_dockerfile();
- $this->build_image();
- $this->stop_running_container();
- $this->start_by_compose_file();
- }
private function generate_build_env_variables()
{
diff --git a/app/Models/Application.php b/app/Models/Application.php
index 9602d45ec..6b730edee 100644
--- a/app/Models/Application.php
+++ b/app/Models/Application.php
@@ -215,4 +215,18 @@ public function deploymentType()
}
throw new \Exception('No deployment type found');
}
+ public function could_set_build_commands(): bool
+ {
+ if ($this->build_pack === 'nixpacks') {
+ return true;
+ }
+ return false;
+ }
+ public function git_based(): bool
+ {
+ if ($this->dockerfile || $this->build_pack === 'dockerfile') {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/app/Models/GithubApp.php b/app/Models/GithubApp.php
index c9badfed1..74462e8d7 100644
--- a/app/Models/GithubApp.php
+++ b/app/Models/GithubApp.php
@@ -6,7 +6,7 @@
class GithubApp extends BaseModel
{
- protected $fillable = ['name', 'uuid', 'organization', 'api_url', 'html_url', 'custom_user', 'custom_port', 'team_id', 'client_secret', 'webhook_secret'];
+ protected $guarded = [];
protected $appends = ['type'];
protected $casts = [
'is_public' => 'boolean',
diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php
index 82f6e4521..2787f153e 100644
--- a/bootstrap/helpers/docker.php
+++ b/bootstrap/helpers/docker.php
@@ -64,3 +64,13 @@ function generate_container_name(string $uuid, int $pull_request_id = 0)
return $uuid;
}
}
+function get_port_from_dockerfile($dockerfile): int
+{
+ $port = preg_grep('/EXPOSE\s+(\d+)/', explode("\n", $dockerfile));
+ if (count($port) > 0 && preg_match('/EXPOSE\s+(\d+)/', $port[1], $matches)) {
+ $port = $matches[1];
+ } else {
+ $port = 80;
+ }
+ return $port;
+}
diff --git a/database/migrations/2023_08_11_190528_add_dockerfile_to_applications_table.php b/database/migrations/2023_08_11_190528_add_dockerfile_to_applications_table.php
new file mode 100644
index 000000000..f2ee10640
--- /dev/null
+++ b/database/migrations/2023_08_11_190528_add_dockerfile_to_applications_table.php
@@ -0,0 +1,25 @@
+longText('dockerfile')->nullable();
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::table('applications', function (Blueprint $table) {
+ $table->dropColumn('dockerfile');
+ });
+ }
+};
diff --git a/database/seeders/ApplicationSeeder.php b/database/seeders/ApplicationSeeder.php
index f5b000662..a43e0f19a 100644
--- a/database/seeders/ApplicationSeeder.php
+++ b/database/seeders/ApplicationSeeder.php
@@ -23,11 +23,27 @@ public function run(): void
'git_branch' => 'nodejs-fastify',
'build_pack' => 'nixpacks',
'ports_exposes' => '3000',
- 'ports_mappings' => '3000:3000',
+ 'ports_mappings' => '3005:3000',
'environment_id' => 1,
'destination_id' => 0,
'destination_type' => StandaloneDocker::class,
- 'source_id' => 1,
+ 'source_id' => 0,
+ 'source_type' => GithubApp::class
+ ]);
+ Application::create([
+ 'name' => 'coollabsio/coolify-examples:dockerfile',
+ 'description' => 'Dockerfile Example',
+ 'fqdn' => 'http://foos.com',
+ 'repository_project_id' => 603035348,
+ 'git_repository' => 'coollabsio/coolify-examples',
+ 'git_branch' => 'dockerfile',
+ 'build_pack' => 'dockerfile',
+ 'ports_exposes' => '3000',
+ 'ports_mappings' => '3080:80',
+ 'environment_id' => 1,
+ 'destination_id' => 0,
+ 'destination_type' => StandaloneDocker::class,
+ 'source_id' => 0,
'source_type' => GithubApp::class
]);
}
diff --git a/database/seeders/GithubAppSeeder.php b/database/seeders/GithubAppSeeder.php
index 1b5143988..4aa5ec753 100644
--- a/database/seeders/GithubAppSeeder.php
+++ b/database/seeders/GithubAppSeeder.php
@@ -13,6 +13,7 @@ class GithubAppSeeder extends Seeder
public function run(): void
{
GithubApp::create([
+ 'id' => 0,
'name' => 'Public GitHub',
'api_url' => 'https://api.github.com',
'html_url' => 'https://github.com',
diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php
index 056a4cd3f..ee55d08a8 100644
--- a/resources/views/dashboard.blade.php
+++ b/resources/views/dashboard.blade.php
@@ -23,7 +23,6 @@
@if (is_dev())
-