From 2b394d6feaba2c07d59289a30a06571b0d52f2b8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sun, 21 Jan 2024 14:30:03 +0100 Subject: [PATCH] fix: show container on logs/executecontainer command views fix: exclude containers with restart: no from hc feat: add compose to predefined docker network service: add glitchtip --- app/Actions/Service/StartService.php | 12 ++-- app/Livewire/Project/Service/StackForm.php | 4 ++ .../Shared/ExecuteContainerCommand.php | 12 ++-- app/Livewire/Project/Shared/Logs.php | 12 ++-- app/View/Components/Forms/Checkbox.php | 2 +- bootstrap/helpers/shared.php | 3 + ..._130328_add_docker_network_to_services.php | 28 +++++++++ .../views/components/forms/checkbox.blade.php | 4 +- .../project/service/stack-form.blade.php | 3 + templates/compose/glitchtip.yaml | 57 +++++++++++++++++++ templates/service-templates.json | 6 ++ 11 files changed, 123 insertions(+), 20 deletions(-) create mode 100644 database/migrations/2024_01_21_130328_add_docker_network_to_services.php create mode 100644 templates/compose/glitchtip.yaml diff --git a/app/Actions/Service/StartService.php b/app/Actions/Service/StartService.php index a90b368ab..cbee5918b 100644 --- a/app/Actions/Service/StartService.php +++ b/app/Actions/Service/StartService.php @@ -12,7 +12,6 @@ class StartService public function handle(Service $service) { ray('Starting service: ' . $service->name); - $network = $service->destination->network; $service->saveComposeConfigs(); $commands[] = "cd " . $service->workdir(); $commands[] = "echo 'Saved configuration files to {$service->workdir()}.'"; @@ -24,10 +23,13 @@ public function handle(Service $service) $commands[] = "echo 'Starting containers.'"; $commands[] = "docker compose up -d --remove-orphans --force-recreate --build"; $commands[] = "docker network connect $service->uuid coolify-proxy >/dev/null 2>&1 || true"; - $compose = data_get($service, 'docker_compose', []); - $serviceNames = data_get(Yaml::parse($compose), 'services', []); - foreach ($serviceNames as $serviceName => $serviceConfig) { - $commands[] = "docker network connect --alias {$serviceName}-{$service->uuid} $network {$serviceName}-{$service->uuid} || true"; + if (data_get($service, 'connect_to_docker_network')) { + $compose = data_get($service, 'docker_compose', []); + $network = $service->destination->network; + $serviceNames = data_get(Yaml::parse($compose), 'services', []); + foreach ($serviceNames as $serviceName => $serviceConfig) { + $commands[] = "docker network connect --alias {$serviceName}-{$service->uuid} $network {$serviceName}-{$service->uuid} || true"; + } } $activity = remote_process($commands, $service->server, type_uuid: $service->uuid, callEventOnFinish: 'ServiceStatusChanged'); return $activity; diff --git a/app/Livewire/Project/Service/StackForm.php b/app/Livewire/Project/Service/StackForm.php index c21f4d8f6..894428182 100644 --- a/app/Livewire/Project/Service/StackForm.php +++ b/app/Livewire/Project/Service/StackForm.php @@ -14,6 +14,7 @@ class StackForm extends Component 'service.docker_compose' => 'required', 'service.name' => 'required', 'service.description' => 'nullable', + 'service.connect_to_docker_network' => 'nullable', ]; public $validationAttributes = []; public function mount() @@ -44,6 +45,9 @@ public function saveCompose($raw) $this->service->docker_compose_raw = $raw; $this->submit(); } + public function instantSave() { + $this->service->save(); + } public function submit() { diff --git a/app/Livewire/Project/Shared/ExecuteContainerCommand.php b/app/Livewire/Project/Shared/ExecuteContainerCommand.php index e3d48cb2b..83df5a15c 100644 --- a/app/Livewire/Project/Shared/ExecuteContainerCommand.php +++ b/app/Livewire/Project/Shared/ExecuteContainerCommand.php @@ -79,21 +79,21 @@ public function getContainers() $this->resource = $resource; $this->server = $this->resource->destination->server; $this->container = $this->resource->uuid; - if (!str(data_get($this,'resource.status'))->startsWith('exited')) { + // if (!str(data_get($this,'resource.status'))->startsWith('exited')) { $this->containers->push($this->container); - } + // } } else if (data_get($this->parameters, 'service_uuid')) { $this->type = 'service'; $this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail(); $this->resource->applications()->get()->each(function ($application) { - if (str(data_get($application, 'status'))->contains('running')) { + // if (str(data_get($application, 'status'))->contains('running')) { $this->containers->push(data_get($application, 'name') . '-' . data_get($this->resource, 'uuid')); - } + // } }); $this->resource->databases()->get()->each(function ($database) { - if (str(data_get($database, 'status'))->contains('running')) { + // if (str(data_get($database, 'status'))->contains('running')) { $this->containers->push(data_get($database, 'name') . '-' . data_get($this->resource, 'uuid')); - } + // } }); $this->server = $this->resource->server; diff --git a/app/Livewire/Project/Shared/Logs.php b/app/Livewire/Project/Shared/Logs.php index a8f41c92e..19edbdd7b 100644 --- a/app/Livewire/Project/Shared/Logs.php +++ b/app/Livewire/Project/Shared/Logs.php @@ -70,21 +70,21 @@ public function mount() $this->status = $this->resource->status; $this->server = $this->resource->destination->server; $this->container = $this->resource->uuid; - if (str(data_get($this, 'resource.status'))->startsWith('running')) { + // if (str(data_get($this, 'resource.status'))->startsWith('running')) { $this->containers->push($this->container); - } + // } } else if (data_get($this->parameters, 'service_uuid')) { $this->type = 'service'; $this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail(); $this->resource->applications()->get()->each(function ($application) { - if (str(data_get($application, 'status'))->contains('running')) { + // if (str(data_get($application, 'status'))->contains('running')) { $this->containers->push(data_get($application, 'name') . '-' . data_get($this->resource, 'uuid')); - } + // } }); $this->resource->databases()->get()->each(function ($database) { - if (str(data_get($database, 'status'))->contains('running')) { + // if (str(data_get($database, 'status'))->contains('running')) { $this->containers->push(data_get($database, 'name') . '-' . data_get($this->resource, 'uuid')); - } + // } }); $this->server = $this->resource->server; diff --git a/app/View/Components/Forms/Checkbox.php b/app/View/Components/Forms/Checkbox.php index 4fd05c2dd..0bbbc1e04 100644 --- a/app/View/Components/Forms/Checkbox.php +++ b/app/View/Components/Forms/Checkbox.php @@ -19,7 +19,7 @@ public function __construct( public string|null $helper = null, public string|bool $instantSave = false, public bool $disabled = false, - public string $defaultClass = "toggle toggle-xs toggle-warning rounded disabled:bg-coolgray-200 disabled:opacity-50 placeholder:text-neutral-700" + public string $defaultClass = "toggle toggle-xs toggle-warning rounded disabled:bg-coolgray-200 disabled:opacity-50 placeholder:text-neutral-700", ) { // } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 2a0e14111..3cff9ba24 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1036,6 +1036,9 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal if (!data_get($service, 'restart')) { data_set($service, 'restart', RESTART_MODE); } + if (data_get($service, 'restart') === 'no') { + $savedService->update(['exclude_from_status' => true]); + } data_set($service, 'container_name', $containerName); data_forget($service, 'volumes.*.content'); data_forget($service, 'volumes.*.isDirectory'); diff --git a/database/migrations/2024_01_21_130328_add_docker_network_to_services.php b/database/migrations/2024_01_21_130328_add_docker_network_to_services.php new file mode 100644 index 000000000..78ea10e3a --- /dev/null +++ b/database/migrations/2024_01_21_130328_add_docker_network_to_services.php @@ -0,0 +1,28 @@ +boolean('connect_to_docker_network')->default(false); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('services', function (Blueprint $table) { + $table->dropColumn('connect_to_docker_network'); + }); + } +}; diff --git a/resources/views/components/forms/checkbox.blade.php b/resources/views/components/forms/checkbox.blade.php index 1265dc132..12ed8edb3 100644 --- a/resources/views/components/forms/checkbox.blade.php +++ b/resources/views/components/forms/checkbox.blade.php @@ -1,6 +1,6 @@
-
+
+ +
@if ($fields)

Service Specific Configuration

diff --git a/templates/compose/glitchtip.yaml b/templates/compose/glitchtip.yaml new file mode 100644 index 000000000..de4848f5b --- /dev/null +++ b/templates/compose/glitchtip.yaml @@ -0,0 +1,57 @@ +version: "3.8" +services: + postgres: + image: postgres:16-alpine + environment: + - POSTGRES_USER=${SERVICE_USER_POSTGRESQL} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRESQL} + - POSTGRES_DB=${POSTGRESQL_DATABASE:-glitchtip} + volumes: + - pg-data:/var/lib/postgresql/data + redis: + image: redis + web: + image: glitchtip/glitchtip + depends_on: + - postgres + - redis + environment: + - SERVICE_FQDN_GLITCHTIP + - DATABASE_URL=postgres://$SERVICE_USER_POSTGRESQL:$SERVICE_PASSWORD_POSTGRESQL@postgres:5432/${POSTGRESQL_DATABASE:-glitchtip} + - SECRET_KEY=$SERVICE_BASE64_64_ENCRYPTION + - EMAIL_URL=${EMAIL_URL:-consolemail://} + - GLITCHTIP_DOMAIN=${SERVICE_FQDN_GLITCHTIP} + - DEFAULT_FROM_EMAIL=${DEFAULT_FROM_EMAIL:-test@example.com} + - CELERY_WORKER_AUTOSCALE=${CELERY_WORKER_AUTOSCALE:-1,3} + - CELERY_WORKER_MAX_TASKS_PER_CHILD=${CELERY_WORKER_MAX_TASKS_PER_CHILD:-10000} + volumes: + - uploads:/code/uploads + worker: + image: glitchtip/glitchtip + command: ./bin/run-celery-with-beat.sh + depends_on: + - postgres + - redis + environment: + - DATABASE_URL=postgres://$SERVICE_USER_POSTGRESQL:$SERVICE_PASSWORD_POSTGRESQL@postgres:5432/${POSTGRESQL_DATABASE:-glitchtip} + - SECRET_KEY=$SERVICE_BASE64_64_ENCRYPTION + - EMAIL_URL=${EMAIL_URL:-consolemail://} + - DEFAULT_FROM_EMAIL=${DEFAULT_FROM_EMAIL:-test@example.com} + - CELERY_WORKER_AUTOSCALE=${CELERY_WORKER_AUTOSCALE:-1,3} + - CELERY_WORKER_MAX_TASKS_PER_CHILD=${CELERY_WORKER_MAX_TASKS_PER_CHILD:-10000} + volumes: + - uploads:/code/uploads + migrate: + image: glitchtip/glitchtip + restart: "no" + depends_on: + - postgres + - redis + command: "./manage.py migrate" + environment: + - DATABASE_URL=postgres://$SERVICE_USER_POSTGRESQL:$SERVICE_PASSWORD_POSTGRESQL@postgres:5432/${POSTGRESQL_DATABASE:-glitchtip} + - SECRET_KEY=$SERVICE_BASE64_64_ENCRYPTION + - EMAIL_URL=${EMAIL_URL:-consolemail://} + - DEFAULT_FROM_EMAIL=${DEFAULT_FROM_EMAIL:-test@example.com} + - CELERY_WORKER_AUTOSCALE=${CELERY_WORKER_AUTOSCALE:-1,3} + - CELERY_WORKER_MAX_TASKS_PER_CHILD=${CELERY_WORKER_MAX_TASKS_PER_CHILD:-10000} diff --git a/templates/service-templates.json b/templates/service-templates.json index f397cc305..4af041067 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -230,6 +230,12 @@ "lightweight" ] }, + "glitchtip": { + "documentation": "https:\/\/coolify.io\/docs", + "slogan": "Glitchtip.yaml", + "compose": "dmVyc2lvbjogJzMuOCcKc2VydmljZXM6CiAgcG9zdGdyZXM6CiAgICBpbWFnZTogJ3Bvc3RncmVzOjE2LWFscGluZScKICAgIGVudmlyb25tZW50OgogICAgICAtICdQT1NUR1JFU19VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTUUx9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVNRTH0nCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7UE9TVEdSRVNRTF9EQVRBQkFTRTotZ2xpdGNodGlwfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3BnLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogIHJlZGlzOgogICAgaW1hZ2U6IHJlZGlzCiAgd2ViOgogICAgaW1hZ2U6IGdsaXRjaHRpcC9nbGl0Y2h0aXAKICAgIGRlcGVuZHNfb246CiAgICAgIC0gcG9zdGdyZXMKICAgICAgLSByZWRpcwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROX0dMSVRDSFRJUAogICAgICAtICdEQVRBQkFTRV9VUkw9cG9zdGdyZXM6Ly8kU0VSVklDRV9VU0VSX1BPU1RHUkVTUUw6JFNFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVNRTEBwb3N0Z3Jlczo1NDMyLyR7UE9TVEdSRVNRTF9EQVRBQkFTRTotZ2xpdGNodGlwfScKICAgICAgLSBTRUNSRVRfS0VZPSRTRVJWSUNFX0JBU0U2NF82NF9FTkNSWVBUSU9OCiAgICAgIC0gJ0VNQUlMX1VSTD0ke0VNQUlMX1VSTDotY29uc29sZW1haWw6Ly99JwogICAgICAtICdHTElUQ0hUSVBfRE9NQUlOPSR7U0VSVklDRV9GUUROX0dMSVRDSFRJUH0nCiAgICAgIC0gJ0RFRkFVTFRfRlJPTV9FTUFJTD0ke0RFRkFVTFRfRlJPTV9FTUFJTDotdGVzdEBleGFtcGxlLmNvbX0nCiAgICAgIC0gJ0NFTEVSWV9XT1JLRVJfQVVUT1NDQUxFPSR7Q0VMRVJZX1dPUktFUl9BVVRPU0NBTEU6LTEsM30nCiAgICAgIC0gJ0NFTEVSWV9XT1JLRVJfTUFYX1RBU0tTX1BFUl9DSElMRD0ke0NFTEVSWV9XT1JLRVJfTUFYX1RBU0tTX1BFUl9DSElMRDotMTAwMDB9JwogICAgdm9sdW1lczoKICAgICAgLSAndXBsb2FkczovY29kZS91cGxvYWRzJwogIHdvcmtlcjoKICAgIGltYWdlOiBnbGl0Y2h0aXAvZ2xpdGNodGlwCiAgICBjb21tYW5kOiAuL2Jpbi9ydW4tY2VsZXJ5LXdpdGgtYmVhdC5zaAogICAgZGVwZW5kc19vbjoKICAgICAgLSBwb3N0Z3JlcwogICAgICAtIHJlZGlzCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnREFUQUJBU0VfVVJMPXBvc3RncmVzOi8vJFNFUlZJQ0VfVVNFUl9QT1NUR1JFU1FMOiRTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTUUxAcG9zdGdyZXM6NTQzMi8ke1BPU1RHUkVTUUxfREFUQUJBU0U6LWdsaXRjaHRpcH0nCiAgICAgIC0gU0VDUkVUX0tFWT0kU0VSVklDRV9CQVNFNjRfNjRfRU5DUllQVElPTgogICAgICAtICdFTUFJTF9VUkw9JHtFTUFJTF9VUkw6LWNvbnNvbGVtYWlsOi8vfScKICAgICAgLSAnREVGQVVMVF9GUk9NX0VNQUlMPSR7REVGQVVMVF9GUk9NX0VNQUlMOi10ZXN0QGV4YW1wbGUuY29tfScKICAgICAgLSAnQ0VMRVJZX1dPUktFUl9BVVRPU0NBTEU9JHtDRUxFUllfV09SS0VSX0FVVE9TQ0FMRTotMSwzfScKICAgICAgLSAnQ0VMRVJZX1dPUktFUl9NQVhfVEFTS1NfUEVSX0NISUxEPSR7Q0VMRVJZX1dPUktFUl9NQVhfVEFTS1NfUEVSX0NISUxEOi0xMDAwMH0nCiAgICB2b2x1bWVzOgogICAgICAtICd1cGxvYWRzOi9jb2RlL3VwbG9hZHMnCiAgbWlncmF0ZToKICAgIGltYWdlOiBnbGl0Y2h0aXAvZ2xpdGNodGlwCiAgICByZXN0YXJ0OiAnbm8nCiAgICBkZXBlbmRzX29uOgogICAgICAtIHBvc3RncmVzCiAgICAgIC0gcmVkaXMKICAgIGNvbW1hbmQ6ICcuL21hbmFnZS5weSBtaWdyYXRlJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ0RBVEFCQVNFX1VSTD1wb3N0Z3JlczovLyRTRVJWSUNFX1VTRVJfUE9TVEdSRVNRTDokU0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU1FMQHBvc3RncmVzOjU0MzIvJHtQT1NUR1JFU1FMX0RBVEFCQVNFOi1nbGl0Y2h0aXB9JwogICAgICAtIFNFQ1JFVF9LRVk9JFNFUlZJQ0VfQkFTRTY0XzY0X0VOQ1JZUFRJT04KICAgICAgLSAnRU1BSUxfVVJMPSR7RU1BSUxfVVJMOi1jb25zb2xlbWFpbDovL30nCiAgICAgIC0gJ0RFRkFVTFRfRlJPTV9FTUFJTD0ke0RFRkFVTFRfRlJPTV9FTUFJTDotdGVzdEBleGFtcGxlLmNvbX0nCiAgICAgIC0gJ0NFTEVSWV9XT1JLRVJfQVVUT1NDQUxFPSR7Q0VMRVJZX1dPUktFUl9BVVRPU0NBTEU6LTEsM30nCiAgICAgIC0gJ0NFTEVSWV9XT1JLRVJfTUFYX1RBU0tTX1BFUl9DSElMRD0ke0NFTEVSWV9XT1JLRVJfTUFYX1RBU0tTX1BFUl9DSElMRDotMTAwMDB9Jwo=", + "tags": null + }, "grafana-with-postgresql": { "documentation": "https:\/\/grafana.com\/docs\/grafana\/latest\/installation\/docker\/", "slogan": "Grafana is the open source analytics & monitoring solution for every database.",