wip: swarm
This commit is contained in:
@@ -19,24 +19,26 @@
|
||||
<div class="flex-1"></div>
|
||||
@if ($application->build_pack === 'dockercompose' && is_null($application->docker_compose_raw))
|
||||
<div>Please load a Compose file.</div>
|
||||
@elseif ($application->destination->server->isSwarm() && str($application->docker_registry_image_name)->isEmpty())
|
||||
Swarm Deployments requires a Docker Image in a Registry.
|
||||
@else
|
||||
<x-applications.advanced :application="$application" />
|
||||
@if (!$application->destination->server->isSwarm())
|
||||
<x-applications.advanced :application="$application" />
|
||||
@endif
|
||||
@if ($application->status !== 'exited')
|
||||
<button title="With rolling update if possible" wire:click='deploy'
|
||||
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-orange-400" viewBox="0 0 24 24"
|
||||
stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path
|
||||
d="M10.09 4.01l.496 -.495a2 2 0 0 1 2.828 0l7.071 7.07a2 2 0 0 1 0 2.83l-7.07 7.07a2 2 0 0 1 -2.83 0l-7.07 -7.07a2 2 0 0 1 0 -2.83l3.535 -3.535h-3.988">
|
||||
</path>
|
||||
<path d="M7.05 11.038v-3.988"></path>
|
||||
</svg>
|
||||
Redeploy
|
||||
</button>
|
||||
@if (!$application->destination->server->isSwarm())
|
||||
<button title="With rolling update if possible" wire:click='deploy'
|
||||
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-orange-400" viewBox="0 0 24 24"
|
||||
stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path
|
||||
d="M10.09 4.01l.496 -.495a2 2 0 0 1 2.828 0l7.071 7.07a2 2 0 0 1 0 2.83l-7.07 7.07a2 2 0 0 1 -2.83 0l-7.07 -7.07a2 2 0 0 1 0 -2.83l3.535 -3.535h-3.988">
|
||||
</path>
|
||||
<path d="M7.05 11.038v-3.988"></path>
|
||||
</svg>
|
||||
Redeploy
|
||||
</button>
|
||||
@endif
|
||||
@if ($application->build_pack !== 'dockercompose')
|
||||
<button title="Restart without rebuilding" wire:click='restart'
|
||||
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
|
||||
@@ -47,9 +49,13 @@
|
||||
<path d="M20 4v5h-5" />
|
||||
</g>
|
||||
</svg>
|
||||
@if ($application->destination->server->isSwarm())
|
||||
Update Service
|
||||
@else
|
||||
Restart
|
||||
@endif
|
||||
</button>
|
||||
@if (isDev())
|
||||
{{-- @if (isDev())
|
||||
<button title="Restart without rebuilding" wire:click='restartNew'
|
||||
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
|
||||
<svg class="w-5 h-5 text-warning" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
@@ -61,7 +67,7 @@
|
||||
</svg>
|
||||
Restart (new)
|
||||
</button>
|
||||
@endif
|
||||
@endif --}}
|
||||
@endif
|
||||
<button wire:click='stop' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-error" viewBox="0 0 24 24" stroke-width="2"
|
||||
@@ -83,7 +89,7 @@
|
||||
</svg>
|
||||
Deploy
|
||||
</button>
|
||||
@if (isDev())
|
||||
{{-- @if (isDev())
|
||||
<button wire:click='deployNew'
|
||||
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-warning" viewBox="0 0 24 24"
|
||||
@@ -94,7 +100,7 @@
|
||||
</svg>
|
||||
Deploy (new)
|
||||
</button>
|
||||
@endif
|
||||
@endif --}}
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<livewire:server.proxy.modal :server="$server" />
|
||||
<div class="flex items-center gap-2">
|
||||
<h1>Server</h1>
|
||||
@if ($server->proxyType() !== 'NONE')
|
||||
@if ($server->proxyType() !== 'NONE' && $server->isFunctional() && !$server->isSwarmWorker())
|
||||
<livewire:server.proxy.status :server="$server" />
|
||||
@endif
|
||||
</div>
|
||||
@@ -20,25 +20,30 @@
|
||||
]) }}">
|
||||
<button>Private Key</button>
|
||||
</a>
|
||||
<a wire:navigate class="{{ request()->routeIs('server.proxy') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.proxy', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
]) }}">
|
||||
<button>Proxy</button>
|
||||
</a>
|
||||
<a wire:navigate class="{{ request()->routeIs('server.destinations') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.destinations', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
]) }}">
|
||||
<button>Destinations</button>
|
||||
</a>
|
||||
<a wire:navigate class="{{ request()->routeIs('server.log-drains') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.log-drains', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
]) }}">
|
||||
<button>Log Drains</button>
|
||||
</a>
|
||||
@if (!$server->isSwarmWorker())
|
||||
<a wire:navigate class="{{ request()->routeIs('server.proxy') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.proxy', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
]) }}">
|
||||
<button>Proxy</button>
|
||||
</a>
|
||||
<a wire:navigate class="{{ request()->routeIs('server.destinations') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.destinations', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
]) }}">
|
||||
<button>Destinations</button>
|
||||
</a>
|
||||
<a wire:navigate class="{{ request()->routeIs('server.log-drains') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.log-drains', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
]) }}">
|
||||
<button>Log Drains</button>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<div class="flex-1"></div>
|
||||
<livewire:server.proxy.deploy :server="$server" />
|
||||
@if ($server->proxyType() !== 'NONE' && $server->isFunctional() && !$server->isSwarmWorker())
|
||||
<livewire:server.proxy.deploy :server="$server" />
|
||||
@endif
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
<div class="flex flex-col gap-4 min-w-fit">
|
||||
<a :class="activeTab === 'general' && 'text-white'"
|
||||
@click.prevent="activeTab = 'general'; window.location.hash = 'general'" href="#">General</a>
|
||||
@if ($application->destination->server->isSwarm())
|
||||
<a :class="activeTab === 'swarm' && 'text-white'"
|
||||
@click.prevent="activeTab = 'swarm'; window.location.hash = 'swarm'" href="#">Swarm
|
||||
Configuration</a>
|
||||
@endif
|
||||
<a :class="activeTab === 'advanced' && 'text-white'"
|
||||
@click.prevent="activeTab = 'advanced'; window.location.hash = 'advanced'" href="#">Advanced</a>
|
||||
@if ($application->build_pack !== 'static')
|
||||
@@ -13,6 +18,7 @@
|
||||
href="#">Environment
|
||||
Variables</a>
|
||||
@endif
|
||||
|
||||
@if ($application->git_based())
|
||||
<a :class="activeTab === 'source' && 'text-white'"
|
||||
@click.prevent="activeTab = 'source'; window.location.hash = 'source'" href="#">Source</a>
|
||||
@@ -56,6 +62,9 @@
|
||||
<div x-cloak x-show="activeTab === 'general'" class="h-full">
|
||||
<livewire:project.application.general :application="$application" />
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'swarm'" class="h-full">
|
||||
<livewire:project.application.swarm :application="$application" />
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'advanced'" class="h-full">
|
||||
<livewire:project.application.advanced :application="$application" />
|
||||
</div>
|
||||
|
||||
@@ -70,8 +70,11 @@
|
||||
@if ($application->build_pack !== 'dockercompose')
|
||||
<h3>Docker Registry</h3>
|
||||
@if ($application->destination->server->isSwarm())
|
||||
<div>Docker Swarm requires the image to be available in a registry. More info <a class="underline"
|
||||
href="https://coolify.io/docs/docker-registries" target="_blank">here</a>.</div>
|
||||
@if ($application->build_pack !== 'dockerimage')
|
||||
<div>Docker Swarm requires the image to be available in a registry. More info <a
|
||||
class="underline" href="https://coolify.io/docs/docker-registries"
|
||||
target="_blank">here</a>.</div>
|
||||
@endif
|
||||
@else
|
||||
@if ($application->build_pack !== 'dockerimage')
|
||||
<div>Push the built image to a docker registry. More info <a class="underline"
|
||||
@@ -135,7 +138,8 @@
|
||||
label="Docker Compose Location"
|
||||
helper="It is calculated together with the Base Directory:<br><span class='text-warning'>{{ Str::start($application->base_directory . $application->docker_compose_location, '/') }}</span>" />
|
||||
</div>
|
||||
<div class="pt-4">The following commands are for advanced use cases. Only modify them if you know what are
|
||||
<div class="pt-4">The following commands are for advanced use cases. Only modify them if you
|
||||
know what are
|
||||
you doing.</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input placeholder="docker compose build"
|
||||
@@ -199,8 +203,10 @@
|
||||
required
|
||||
helper="A comma separated list of ports your application uses. The first port will be used as default healthcheck port if nothing defined in the Healthcheck menu. Be sure to set this correctly." />
|
||||
@endif
|
||||
<x-forms.input placeholder="3000:3000" id="application.ports_mappings" label="Ports Mappings"
|
||||
helper="A comma separated list of ports you would like to map to the host system. Useful when you do not want to use domains.<br><br><span class='inline-block font-bold text-warning'>Example:</span><br>3000:3000,3002:3002<br><br>Rolling update is not supported if you have a port mapped to the host." />
|
||||
@if (!$application->destination->server->isSwarm())
|
||||
<x-forms.input placeholder="3000:3000" id="application.ports_mappings" label="Ports Mappings"
|
||||
helper="A comma separated list of ports you would like to map to the host system. Useful when you do not want to use domains.<br><br><span class='inline-block font-bold text-warning'>Example:</span><br>3000:3000,3002:3002<br><br>Rolling update is not supported if you have a port mapped to the host." />
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.textarea label="Container Labels" rows="15" id="customLabels"></x-forms.textarea>
|
||||
<x-forms.button wire:click="resetDefaultLabels">Reset to Coolify Generated Labels</x-forms.button>
|
||||
|
||||
24
resources/views/livewire/project/application/swarm.blade.php
Normal file
24
resources/views/livewire/project/application/swarm.blade.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<div>
|
||||
<form wire:submit='submit' class="flex flex-col">
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Swarm Configuration</h2>
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
{{-- <div>Advanced Swarm Configuration</div> --}}
|
||||
<div class="flex flex-col gap-2 py-4">
|
||||
<div class="flex flex-col items-end gap-2 xl:flex-row">
|
||||
<x-forms.input id="application.swarm_replicas" label="Replicas" required />
|
||||
<x-forms.checkbox instantSave helper="If turned off, this resource will start on manager nodes too."
|
||||
id="application.settings.is_swarm_only_worker_nodes" label="Only Start on Worker nodes" />
|
||||
</div>
|
||||
<x-forms.textarea id="swarm_placement_constraints" rows="7"
|
||||
label="Custom Placement Constraints"
|
||||
placeholder="placement:
|
||||
constraints:
|
||||
- 'node.role == worker'" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
@@ -202,6 +202,14 @@
|
||||
<li class="step step-secondary">Select a Server</li>
|
||||
<li class="step">Select a Destination</li>
|
||||
</ul>
|
||||
@if ($isDatabase)
|
||||
<div class="flex items-center justify-center pt-4">
|
||||
<x-forms.checkbox instantSave wire:model="includeSwarm"
|
||||
helper="Swarm clusters are excluded from this list by default. For database (or services with database) to work with Swarm,
|
||||
you need to set a few things on the server. Read more <a class='text-white underline' href='https://coolify.io/docs/swarm#database-requirements' target='_blank'>here</a>."
|
||||
label="Include Swarm Clusters" />
|
||||
</div>
|
||||
@endif
|
||||
<div class="flex flex-col justify-center gap-2 text-left xl:flex-row xl:flex-wrap">
|
||||
@forelse($servers as $server)
|
||||
<div class="box group" wire:click="setServer({{ $server }})">
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
<dialog id="newStorage" class="modal">
|
||||
<form method="dialog" class="flex flex-col gap-2 rounded modal-box" wire:submit='submit'>
|
||||
<h3 class="text-lg font-bold">Add Storage Volume</h3>
|
||||
<x-forms.input placeholder="pv-name" id="name" label="Name" required />
|
||||
<x-forms.input placeholder="/root" id="host_path" label="Source Path" />
|
||||
<x-forms.input placeholder="/tmp/root" id="mount_path" label="Destination Path" required />
|
||||
<x-forms.button onclick="newStorage.close()" type="submit">
|
||||
@if ($isSwarm)
|
||||
<h5>Swarm Mode detected: You need to set a shared volume (EFS/NFS/etc) on all the worker nodes if you would like to use a persistent volumes.</h5>
|
||||
@endif
|
||||
<x-forms.input placeholder="pv-name" id="name" label="Name" required helper="Volume name." />
|
||||
@if ($isSwarm)
|
||||
<x-forms.input placeholder="/root" id="host_path" label="Source Path" required helper="Directory on the host system." />
|
||||
@else
|
||||
<x-forms.input placeholder="/root" id="host_path" label="Source Path" helper="Directory on the host system." />
|
||||
@endif
|
||||
<x-forms.input placeholder="/tmp/root" id="mount_path" label="Destination Path" required helper="Directory inside the container." />
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</form>
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
<script>
|
||||
document.addEventListener('livewire:initialized', () => {
|
||||
Livewire.on('closeStorageModal', () => {
|
||||
document.getElementById('newStorage').close()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</dialog>
|
||||
|
||||
@@ -35,8 +35,10 @@
|
||||
<div class="flex flex-col w-full gap-2 lg:flex-row">
|
||||
<x-forms.input id="server.name" label="Name" required />
|
||||
<x-forms.input id="server.description" label="Description" />
|
||||
<x-forms.input placeholder="https://example.com" id="wildcard_domain" label="Wildcard Domain"
|
||||
helper="Wildcard domain for your applications. If you set this, you will get a random generated domain for your new applications.<br><span class='font-bold text-white'>Example:</span><br>In case you set:<span class='text-helper'>https://example.com</span> your applications will get:<br> <span class='text-helper'>https://randomId.example.com</span>" />
|
||||
@if (!$server->settings->is_swarm_worker)
|
||||
<x-forms.input placeholder="https://example.com" id="wildcard_domain" label="Wildcard Domain"
|
||||
helper="Wildcard domain for your applications. If you set this, you will get a random generated domain for your new applications.<br><span class='font-bold text-white'>Example:</span><br>In case you set:<span class='text-helper'>https://example.com</span> your applications will get:<br> <span class='text-helper'>https://randomId.example.com</span>" />
|
||||
@endif
|
||||
|
||||
</div>
|
||||
<div class="flex flex-col w-full gap-2 lg:flex-row">
|
||||
@@ -53,10 +55,20 @@
|
||||
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all ssh requests to your server through Cloudflare.<span class='text-warning'>Coolify does not install/setup Cloudflare (cloudflared) on your server.</span>"
|
||||
id="server.settings.is_cloudflare_tunnel" label="Cloudflare Tunnel" />
|
||||
@endif
|
||||
<x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_manager"
|
||||
label="Is it a Swarm Manager?" />
|
||||
{{-- <x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_worker"
|
||||
label="Is it a Swarm Worker?" /> --}}
|
||||
@if ($server->settings->is_swarm_worker)
|
||||
<x-forms.checkbox disabled instantSave type="checkbox" id="server.settings.is_swarm_manager"
|
||||
label="Is it a Swarm Manager?" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_manager"
|
||||
label="Is it a Swarm Manager?" />
|
||||
@endif
|
||||
@if ($server->settings->is_swarm_manager)
|
||||
<x-forms.checkbox disabled instantSave type="checkbox" id="server.settings.is_swarm_worker"
|
||||
label="Is it a Swarm Worker?" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_worker"
|
||||
label="Is it a Swarm Worker?" />
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -26,8 +26,19 @@
|
||||
@endforeach
|
||||
</x-forms.select>
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox type="checkbox" id="is_swarm_manager"
|
||||
label="Is it a Swarm Manager?" />
|
||||
@if ($is_swarm_worker)
|
||||
<x-forms.checkbox disabled instantSave type="checkbox" id="is_swarm_manager"
|
||||
label="Is it a Swarm Manager?" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave type="checkbox" id="is_swarm_manager"
|
||||
label="Is it a Swarm Manager?" />
|
||||
@endif
|
||||
@if ($is_swarm_manager)
|
||||
<x-forms.checkbox disabled instantSave type="checkbox" id="is_swarm_worker"
|
||||
label="Is it a Swarm Worker?" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave type="checkbox" id="is_swarm_worker" label="Is it a Swarm Worker?" />
|
||||
@endif
|
||||
</div>
|
||||
<x-forms.button type="submit">
|
||||
Save New Server
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
<div class="flex gap-2">
|
||||
<x-server.sidebar :server="$server" :parameters="$parameters" />
|
||||
<div class="w-full">
|
||||
<livewire:server.proxy :server="$server" />
|
||||
@if ($server->proxyType() !== 'NONE' && $server->isFunctional())
|
||||
<livewire:server.proxy :server="$server" />
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user