commit
4792146f1d
@ -32,13 +32,14 @@ class DeleteService
|
||||
}
|
||||
$database->forceDelete();
|
||||
}
|
||||
foreach ($storagesToDelete as $storage) {
|
||||
$commands[] = "docker volume rm -f $storage->name";
|
||||
if ($server->isFunctional()) {
|
||||
foreach ($storagesToDelete as $storage) {
|
||||
$commands[] = "docker volume rm -f $storage->name";
|
||||
}
|
||||
$commands[] = "docker rm -f $service->uuid";
|
||||
|
||||
instant_remote_process($commands, $server, false);
|
||||
}
|
||||
$commands[] = "docker rm -f $service->uuid";
|
||||
|
||||
instant_remote_process($commands, $server, false);
|
||||
|
||||
$service->forceDelete();
|
||||
}
|
||||
}
|
||||
|
@ -1128,6 +1128,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
|
||||
data_forget($docker_compose, 'services.' . $this->container_name);
|
||||
|
||||
$custom_compose = convert_docker_run_to_compose($this->application->custom_docker_run_options);
|
||||
if (count($custom_compose) > 0) {
|
||||
$docker_compose['services'][$this->application->uuid] = array_merge_recursive($docker_compose['services'][$this->application->uuid], $custom_compose);
|
||||
}
|
||||
|
||||
$this->docker_compose = Yaml::dump($docker_compose, 10);
|
||||
$this->docker_compose_base64 = base64_encode($this->docker_compose);
|
||||
$this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->docker_compose_base64}' | base64 -d > {$this->workdir}/docker-compose.yml"), "hidden" => true]);
|
||||
|
@ -61,11 +61,12 @@ class General extends Component
|
||||
'application.docker_compose_pr' => 'nullable',
|
||||
'application.docker_compose_raw' => 'nullable',
|
||||
'application.docker_compose_pr_raw' => 'nullable',
|
||||
'application.custom_labels' => 'nullable',
|
||||
'application.dockerfile_target_build' => 'nullable',
|
||||
'application.settings.is_static' => 'boolean|required',
|
||||
'application.docker_compose_custom_start_command' => 'nullable',
|
||||
'application.docker_compose_custom_build_command' => 'nullable',
|
||||
'application.custom_labels' => 'nullable',
|
||||
'application.custom_docker_run_options' => 'nullable',
|
||||
'application.settings.is_static' => 'boolean|required',
|
||||
'application.settings.is_raw_compose_deployment_enabled' => 'boolean|required',
|
||||
'application.settings.is_build_server_enabled' => 'boolean|required',
|
||||
];
|
||||
@ -97,9 +98,10 @@ class General extends Component
|
||||
'application.docker_compose_pr_raw' => 'Docker compose raw',
|
||||
'application.custom_labels' => 'Custom labels',
|
||||
'application.dockerfile_target_build' => 'Dockerfile target build',
|
||||
'application.settings.is_static' => 'Is static',
|
||||
'application.custom_docker_run_options' => 'Custom docker run commands',
|
||||
'application.docker_compose_custom_start_command' => 'Docker compose custom start command',
|
||||
'application.docker_compose_custom_build_command' => 'Docker compose custom build command',
|
||||
'application.settings.is_static' => 'Is static',
|
||||
'application.settings.is_raw_compose_deployment_enabled' => 'Is raw compose deployment enabled',
|
||||
'application.settings.is_build_server_enabled' => 'Is build server enabled',
|
||||
];
|
||||
@ -249,6 +251,9 @@ class General extends Component
|
||||
$this->application->fqdn = $domains->implode(',');
|
||||
}
|
||||
|
||||
if (data_get($this->application, 'custom_docker_run_options')) {
|
||||
$this->application->custom_docker_run_options = str($this->application->custom_docker_run_options)->trim();
|
||||
}
|
||||
if (data_get($this->application, 'dockerfile')) {
|
||||
$port = get_port_from_dockerfile($this->application->dockerfile);
|
||||
if ($port && !$this->application->ports_exposes) {
|
||||
|
@ -905,8 +905,7 @@ class Application extends BaseModel
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && git checkout $pr_branch_name";
|
||||
}
|
||||
if ($git_type === 'github') {
|
||||
} else if ($git_type === 'github') {
|
||||
$branch = "pull/{$pull_request_id}/head:$pr_branch_name";
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
@ -914,6 +913,13 @@ class Application extends BaseModel
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && git checkout $pr_branch_name";
|
||||
} else if ($git_type === 'bitbucket') {
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git checkout $commit";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,7 @@
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Models\Server;
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
use App\Models\ServiceDatabase;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Url\Url;
|
||||
@ -323,3 +321,89 @@ function isDatabaseImage(?string $image = null)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function convert_docker_run_to_compose(?string $custom_docker_run_options = null)
|
||||
{
|
||||
$options = [];
|
||||
$compose_options = collect([]);
|
||||
preg_match_all('/(--\w+(?:-\w+)*)(?:\s|=)?([^\s-]+)?/', $custom_docker_run_options, $matches, PREG_SET_ORDER);
|
||||
$list_options = collect([
|
||||
'--cap-add',
|
||||
'--cap-drop',
|
||||
'--security-opt',
|
||||
'--sysctl',
|
||||
'--ulimit',
|
||||
'--device'
|
||||
]);
|
||||
$mapping = collect([
|
||||
'--cap-add' => 'cap_add',
|
||||
'--cap-drop' => 'cap_drop',
|
||||
'--security-opt' => 'security_opt',
|
||||
'--sysctl' => 'sysctls',
|
||||
'--device' => 'devices',
|
||||
'--ulimit' => 'ulimits',
|
||||
'--init' => 'init',
|
||||
'--ulimit' => 'ulimits',
|
||||
'--privileged' => 'privileged',
|
||||
]);
|
||||
foreach ($matches as $match) {
|
||||
$option = $match[1];
|
||||
$value = isset($match[2]) && $match[2] !== '' ? $match[2] : true;
|
||||
if ($list_options->contains($option)) {
|
||||
$value = explode(',', $value);
|
||||
}
|
||||
if (array_key_exists($option, $options)) {
|
||||
if (is_array($options[$option])) {
|
||||
$options[$option][] = $value;
|
||||
} else {
|
||||
$options[$option] = [$options[$option], $value];
|
||||
}
|
||||
} else {
|
||||
$options[$option] = $value;
|
||||
}
|
||||
}
|
||||
$options = collect($options);
|
||||
// Easily get mappings from https://github.com/composerize/composerize/blob/master/packages/composerize/src/mappings.js
|
||||
foreach ($options as $option => $value) {
|
||||
if (!data_get($mapping, $option)) {
|
||||
continue;
|
||||
}
|
||||
if ($option === '--ulimit') {
|
||||
$ulimits = collect([]);
|
||||
collect($value)->map(function ($ulimit) use ($ulimits){
|
||||
$ulimit = explode('=', $ulimit);
|
||||
$type = $ulimit[0];
|
||||
$limits = explode(':', $ulimit[1]);
|
||||
if (count($limits) == 2) {
|
||||
$soft_limit = $limits[0];
|
||||
$hard_limit = $limits[1];
|
||||
$ulimits->put($type, [
|
||||
'soft' => $soft_limit,
|
||||
'hard' => $hard_limit
|
||||
]);
|
||||
|
||||
} else {
|
||||
$soft_limit = $ulimit[1];
|
||||
$ulimits->put($type, [
|
||||
'soft' => $soft_limit,
|
||||
]);
|
||||
}
|
||||
});
|
||||
$compose_options->put($mapping[$option], $ulimits);
|
||||
} else {
|
||||
if ($list_options->contains($option)) {
|
||||
if ($compose_options->has($mapping[$option])) {
|
||||
$compose_options->put($mapping[$option], $options->get($mapping[$option]) . ',' . $value);
|
||||
} else {
|
||||
$compose_options->put($mapping[$option], $value);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
$compose_options->put($mapping[$option], $value);
|
||||
continue;
|
||||
}
|
||||
$compose_options->forget($option);
|
||||
}
|
||||
}
|
||||
return $compose_options->toArray();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ return [
|
||||
|
||||
// The release version of your application
|
||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||
'release' => '4.0.0-beta.201',
|
||||
'release' => '4.0.0-beta.202',
|
||||
// When left empty or `null` the Laravel environment will be used
|
||||
'environment' => config('app.env'),
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
<?php
|
||||
|
||||
return '4.0.0-beta.201';
|
||||
return '4.0.0-beta.202';
|
||||
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->string('custom_docker_run_options')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->dropColumn('custom_docker_run_options');
|
||||
});
|
||||
}
|
||||
};
|
@ -130,7 +130,6 @@
|
||||
@endif
|
||||
@if ($application->could_set_build_commands())
|
||||
@if ($application->build_pack === 'nixpacks')
|
||||
|
||||
<div class="flex flex-col gap-2 xl:flex-row">
|
||||
<x-forms.input placeholder="If you modify this, you probably need to have a nixpacks.toml"
|
||||
id="application.install_command" label="Install Command" />
|
||||
@ -194,6 +193,13 @@
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
<div>The following options are for advanced use cases. Only modify them if you
|
||||
know what are
|
||||
you doing.</div>
|
||||
<x-forms.input
|
||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='text-white underline' href='https://coolify.io/docs/custom-docker-options'>docs.</a>"
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||
id="application.custom_docker_run_options" label="Custom Docker Options" />
|
||||
@endif
|
||||
|
||||
@endif
|
||||
|
@ -14,7 +14,7 @@
|
||||
~/.ssh/authorized_keys
|
||||
file</span>
|
||||
<x-forms.button type="submit">
|
||||
Save Private Key
|
||||
Continue
|
||||
</x-forms.button>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -277,14 +277,6 @@ Route::post('/source/bitbucket/events/manual', function () {
|
||||
]);
|
||||
}
|
||||
foreach ($applications as $application) {
|
||||
if (!$application->isPRDeployable()) {
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Preview deployments disabled.',
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
$webhook_secret = data_get($application, 'manual_webhook_secret_bitbucket');
|
||||
$payload = request()->getContent();
|
||||
|
||||
@ -310,7 +302,7 @@ Route::post('/source/bitbucket/events/manual', function () {
|
||||
continue;
|
||||
}
|
||||
if ($x_bitbucket_event === 'repo:push') {
|
||||
if ($application->isPRDeployable()) {
|
||||
if ($application->isDeployable()) {
|
||||
ray('Deploying ' . $application->name . ' with branch ' . $branch);
|
||||
$deployment_uuid = new Cuid2(7);
|
||||
queue_application_deployment(
|
||||
@ -328,7 +320,7 @@ Route::post('/source/bitbucket/events/manual', function () {
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Preview deployments disabled.',
|
||||
'message' => 'Auto deployment disabled.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
"version": "3.12.36"
|
||||
},
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.201"
|
||||
"version": "4.0.0-beta.202"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user