feat: dockerfile build pack
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Dev;
|
||||
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use Livewire\Component;
|
||||
|
||||
class ScheduledBackups extends Component
|
||||
{
|
||||
public $scheduledDatabaseBackup;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->scheduledDatabaseBackup = ScheduledDatabaseBackup::all();
|
||||
}
|
||||
}
|
||||
@@ -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 @@ class General extends Component
|
||||
$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, '/');
|
||||
}
|
||||
|
||||
68
app/Http/Livewire/Project/New/SimpleDockerfile.php
Normal file
68
app/Http/Livewire/Project/New/SimpleDockerfile.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Project\New;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\GithubApp;
|
||||
use App\Models\Project;
|
||||
use App\Models\StandaloneDocker;
|
||||
use App\Models\SwarmDocker;
|
||||
use Livewire\Component;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
class SimpleDockerfile extends Component
|
||||
{
|
||||
public string $dockerfile = '';
|
||||
public array $parameters;
|
||||
public array $query;
|
||||
public function mount()
|
||||
{
|
||||
$this->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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,10 @@ class Show extends Component
|
||||
$this->parameters = get_route_parameters();
|
||||
}
|
||||
|
||||
public function instantSave()
|
||||
{
|
||||
$this->submit();
|
||||
}
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
@@ -117,10 +117,14 @@ class ApplicationDeploymentJob implements ShouldQueue
|
||||
'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 @@ class ApplicationDeploymentJob implements ShouldQueue
|
||||
);
|
||||
}
|
||||
}
|
||||
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 @@ class ApplicationDeploymentJob implements ShouldQueue
|
||||
$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 @@ class ApplicationDeploymentJob implements ShouldQueue
|
||||
);
|
||||
}
|
||||
|
||||
private function generate_buildpack()
|
||||
private function generate_nixpacks_confs()
|
||||
{
|
||||
$this->execute_remote_command(
|
||||
[
|
||||
@@ -589,49 +662,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
||||
);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
||||
@@ -215,4 +215,18 @@ class Application extends BaseModel
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
|
||||
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',
|
||||
|
||||
Reference in New Issue
Block a user