wip: swarm
This commit is contained in:
parent
c505a6ce9c
commit
b4874c7df3
@ -11,29 +11,34 @@ class StopApplication
|
|||||||
public function handle(Application $application)
|
public function handle(Application $application)
|
||||||
{
|
{
|
||||||
$server = $application->destination->server;
|
$server = $application->destination->server;
|
||||||
$containers = getCurrentApplicationContainerStatus($server, $application->id, 0);
|
if ($server->isSwarm()) {
|
||||||
if ($containers->count() > 0) {
|
instant_remote_process(["docker stack rm {$application->uuid}" ], $server);
|
||||||
foreach ($containers as $container) {
|
} else {
|
||||||
$containerName = data_get($container, 'Names');
|
$containers = getCurrentApplicationContainerStatus($server, $application->id, 0);
|
||||||
if ($containerName) {
|
if ($containers->count() > 0) {
|
||||||
instant_remote_process(
|
foreach ($containers as $container) {
|
||||||
["docker rm -f {$containerName}"],
|
$containerName = data_get($container, 'Names');
|
||||||
$server
|
if ($containerName) {
|
||||||
);
|
instant_remote_process(
|
||||||
|
["docker rm -f {$containerName}"],
|
||||||
|
$server
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: make notification for application
|
||||||
|
// $application->environment->project->team->notify(new StatusChanged($application));
|
||||||
}
|
}
|
||||||
// TODO: make notification for application
|
// Delete Preview Deployments
|
||||||
// $application->environment->project->team->notify(new StatusChanged($application));
|
$previewDeployments = $application->previews;
|
||||||
}
|
foreach ($previewDeployments as $previewDeployment) {
|
||||||
// Delete Preview Deployments
|
$containers = getCurrentApplicationContainerStatus($server, $application->id, $previewDeployment->pull_request_id);
|
||||||
$previewDeployments = $application->previews;
|
foreach ($containers as $container) {
|
||||||
foreach ($previewDeployments as $previewDeployment) {
|
$name = str_replace('/', '', $container['Names']);
|
||||||
$containers = getCurrentApplicationContainerStatus($server, $application->id, $previewDeployment->pull_request_id);
|
instant_remote_process(["docker rm -f $name"], $application->destination->server, throwError: false);
|
||||||
foreach ($containers as $container) {
|
}
|
||||||
$name = str_replace('/', '', $container['Names']);
|
|
||||||
instant_remote_process(["docker rm -f $name"], $application->destination->server, throwError: false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,6 @@ class Dashboard extends Component
|
|||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->servers = Server::ownedByCurrentTeam()->get();
|
$this->servers = Server::ownedByCurrentTeam()->get();
|
||||||
ray($this->servers[1]);
|
|
||||||
ray($this->servers[1]->standaloneDockers);
|
|
||||||
$this->projects = Project::ownedByCurrentTeam()->get();
|
$this->projects = Project::ownedByCurrentTeam()->get();
|
||||||
}
|
}
|
||||||
// public function getIptables()
|
// public function getIptables()
|
||||||
|
@ -126,7 +126,6 @@ class Select extends Component
|
|||||||
{
|
{
|
||||||
$this->server_id = $server->id;
|
$this->server_id = $server->id;
|
||||||
$this->standaloneDockers = $server->standaloneDockers;
|
$this->standaloneDockers = $server->standaloneDockers;
|
||||||
ray($server);
|
|
||||||
$this->swarmDockers = $server->swarmDockers;
|
$this->swarmDockers = $server->swarmDockers;
|
||||||
$this->current_step = 'destinations';
|
$this->current_step = 'destinations';
|
||||||
}
|
}
|
||||||
|
@ -156,25 +156,27 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
|
|
||||||
// Generate custom host<->ip mapping
|
// Generate custom host<->ip mapping
|
||||||
$allContainers = instant_remote_process(["docker network inspect {$this->destination->network} -f '{{json .Containers}}' "], $this->server);
|
$allContainers = instant_remote_process(["docker network inspect {$this->destination->network} -f '{{json .Containers}}' "], $this->server);
|
||||||
$allContainers = format_docker_command_output_to_json($allContainers);
|
if (!is_null($allContainers)) {
|
||||||
$ips = collect([]);
|
$allContainers = format_docker_command_output_to_json($allContainers);
|
||||||
if (count($allContainers) > 0) {
|
$ips = collect([]);
|
||||||
$allContainers = $allContainers[0];
|
if (count($allContainers) > 0) {
|
||||||
foreach ($allContainers as $container) {
|
$allContainers = $allContainers[0];
|
||||||
$containerName = data_get($container, 'Name');
|
foreach ($allContainers as $container) {
|
||||||
if ($containerName === 'coolify-proxy') {
|
$containerName = data_get($container, 'Name');
|
||||||
continue;
|
if ($containerName === 'coolify-proxy') {
|
||||||
}
|
continue;
|
||||||
$containerIp = data_get($container, 'IPv4Address');
|
}
|
||||||
if ($containerName && $containerIp) {
|
$containerIp = data_get($container, 'IPv4Address');
|
||||||
$containerIp = str($containerIp)->before('/');
|
if ($containerName && $containerIp) {
|
||||||
$ips->put($containerName, $containerIp->value());
|
$containerIp = str($containerIp)->before('/');
|
||||||
|
$ips->put($containerName, $containerIp->value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$this->addHosts = $ips->map(function ($ip, $name) {
|
||||||
|
return "--add-host $name:$ip";
|
||||||
|
})->implode(' ');
|
||||||
}
|
}
|
||||||
$this->addHosts = $ips->map(function ($ip, $name) {
|
|
||||||
return "--add-host $name:$ip";
|
|
||||||
})->implode(' ');
|
|
||||||
|
|
||||||
if ($this->application->dockerfile_target_build) {
|
if ($this->application->dockerfile_target_build) {
|
||||||
$this->buildTarget = " --target {$this->application->dockerfile_target_build} ";
|
$this->buildTarget = " --target {$this->application->dockerfile_target_build} ";
|
||||||
@ -214,6 +216,14 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
}
|
}
|
||||||
if ($this->application->docker_registry_image_name && $this->application->build_pack !== 'dockerimage') {
|
if ($this->application->docker_registry_image_name && $this->application->build_pack !== 'dockerimage') {
|
||||||
$this->push_to_docker_registry();
|
$this->push_to_docker_registry();
|
||||||
|
if ($this->server->isSwarm()) {
|
||||||
|
$this->application_deployment_queue->addLogEntry("Creating / updating stack.");
|
||||||
|
$this->execute_remote_command(
|
||||||
|
[
|
||||||
|
"docker stack deploy --with-registry-auth --prune --compose-file {$this->configuration_dir}/docker-compose.yml {$this->application->uuid}"
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$this->next(ApplicationDeploymentStatus::FINISHED->value);
|
$this->next(ApplicationDeploymentStatus::FINISHED->value);
|
||||||
$this->application->isConfigurationChanged(true);
|
$this->application->isConfigurationChanged(true);
|
||||||
@ -534,75 +544,83 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
|
|
||||||
private function rolling_update()
|
private function rolling_update()
|
||||||
{
|
{
|
||||||
if (count($this->application->ports_mappings_array) > 0) {
|
if ($this->server->isSwarm()) {
|
||||||
$this->execute_remote_command(
|
// Skip this.
|
||||||
[
|
|
||||||
"echo '\n----------------------------------------'",
|
|
||||||
],
|
|
||||||
["echo -n 'Application has ports mapped to the host system, rolling update is not supported.'"],
|
|
||||||
);
|
|
||||||
$this->stop_running_container(force: true);
|
|
||||||
$this->start_by_compose_file();
|
|
||||||
} else {
|
} else {
|
||||||
$this->execute_remote_command(
|
if (count($this->application->ports_mappings_array) > 0) {
|
||||||
[
|
$this->execute_remote_command(
|
||||||
"echo '\n----------------------------------------'",
|
[
|
||||||
],
|
"echo '\n----------------------------------------'",
|
||||||
["echo -n 'Rolling update started.'"],
|
],
|
||||||
);
|
["echo -n 'Application has ports mapped to the host system, rolling update is not supported.'"],
|
||||||
$this->start_by_compose_file();
|
);
|
||||||
$this->health_check();
|
$this->stop_running_container(force: true);
|
||||||
$this->stop_running_container();
|
$this->start_by_compose_file();
|
||||||
$this->application_deployment_queue->addLogEntry("Rolling update completed.");
|
} else {
|
||||||
|
$this->execute_remote_command(
|
||||||
|
[
|
||||||
|
"echo '\n----------------------------------------'",
|
||||||
|
],
|
||||||
|
["echo -n 'Rolling update started.'"],
|
||||||
|
);
|
||||||
|
$this->start_by_compose_file();
|
||||||
|
$this->health_check();
|
||||||
|
$this->stop_running_container();
|
||||||
|
$this->application_deployment_queue->addLogEntry("Rolling update completed.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private function health_check()
|
private function health_check()
|
||||||
{
|
{
|
||||||
if ($this->application->isHealthcheckDisabled()) {
|
if ($this->server->isSwarm()) {
|
||||||
$this->newVersionIsHealthy = true;
|
// Implement healthcheck for swarm
|
||||||
return;
|
} else {
|
||||||
}
|
if ($this->application->isHealthcheckDisabled()) {
|
||||||
// ray('New container name: ', $this->container_name);
|
$this->newVersionIsHealthy = true;
|
||||||
if ($this->container_name) {
|
return;
|
||||||
$counter = 1;
|
}
|
||||||
$this->execute_remote_command(
|
// ray('New container name: ', $this->container_name);
|
||||||
[
|
if ($this->container_name) {
|
||||||
"echo 'Waiting for healthcheck to pass on the new container.'"
|
$counter = 1;
|
||||||
]
|
|
||||||
);
|
|
||||||
if ($this->full_healthcheck_url) {
|
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
[
|
[
|
||||||
"echo 'Healthcheck URL (inside the container): {$this->full_healthcheck_url}'"
|
"echo 'Waiting for healthcheck to pass on the new container.'"
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
if ($this->full_healthcheck_url) {
|
||||||
while ($counter < $this->application->health_check_retries) {
|
|
||||||
$this->execute_remote_command(
|
|
||||||
[
|
|
||||||
"docker inspect --format='{{json .State.Health.Status}}' {$this->container_name}",
|
|
||||||
"hidden" => true,
|
|
||||||
"save" => "health_check"
|
|
||||||
],
|
|
||||||
|
|
||||||
);
|
|
||||||
$this->execute_remote_command(
|
|
||||||
[
|
|
||||||
"echo 'Attempt {$counter} of {$this->application->health_check_retries} | Healthcheck status: {$this->saved_outputs->get('health_check')}'"
|
|
||||||
],
|
|
||||||
);
|
|
||||||
if (Str::of($this->saved_outputs->get('health_check'))->contains('healthy')) {
|
|
||||||
$this->newVersionIsHealthy = true;
|
|
||||||
$this->application->update(['status' => 'running']);
|
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
[
|
[
|
||||||
"echo 'New container is healthy.'"
|
"echo 'Healthcheck URL (inside the container): {$this->full_healthcheck_url}'"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
while ($counter < $this->application->health_check_retries) {
|
||||||
|
$this->execute_remote_command(
|
||||||
|
[
|
||||||
|
"docker inspect --format='{{json .State.Health.Status}}' {$this->container_name}",
|
||||||
|
"hidden" => true,
|
||||||
|
"save" => "health_check"
|
||||||
|
],
|
||||||
|
|
||||||
|
);
|
||||||
|
$this->execute_remote_command(
|
||||||
|
[
|
||||||
|
"echo 'Attempt {$counter} of {$this->application->health_check_retries} | Healthcheck status: {$this->saved_outputs->get('health_check')}'"
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
break;
|
if (Str::of($this->saved_outputs->get('health_check'))->contains('healthy')) {
|
||||||
|
$this->newVersionIsHealthy = true;
|
||||||
|
$this->application->update(['status' => 'running']);
|
||||||
|
$this->execute_remote_command(
|
||||||
|
[
|
||||||
|
"echo 'New container is healthy.'"
|
||||||
|
],
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$counter++;
|
||||||
|
sleep($this->application->health_check_interval);
|
||||||
}
|
}
|
||||||
$counter++;
|
|
||||||
sleep($this->application->health_check_interval);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -849,21 +867,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
}
|
}
|
||||||
if ($this->pull_request_id !== 0) {
|
if ($this->pull_request_id !== 0) {
|
||||||
$labels = collect(generateLabelsApplication($this->application, $this->preview));
|
$labels = collect(generateLabelsApplication($this->application, $this->preview));
|
||||||
|
|
||||||
// $newHostLabel = $newLabels->filter(function ($label) {
|
|
||||||
// return str($label)->contains('Host');
|
|
||||||
// });
|
|
||||||
// $labels = $labels->reject(function ($label) {
|
|
||||||
// return str($label)->contains('Host');
|
|
||||||
// });
|
|
||||||
// ray($labels,$newLabels);
|
|
||||||
// $labels = $labels->map(function ($label) {
|
|
||||||
// $pattern = '/([a-zA-Z0-9]+)-(\d+)-(http|https)/';
|
|
||||||
// $replacement = "$1-pr-{$this->pull_request_id}-$2-$3";
|
|
||||||
// $newLabel = preg_replace($pattern, $replacement, $label);
|
|
||||||
// return $newLabel;
|
|
||||||
// });
|
|
||||||
// $labels = $labels->merge($newHostLabel);
|
|
||||||
}
|
}
|
||||||
$labels = $labels->merge(defaultLabels($this->application->id, $this->application->uuid, $this->pull_request_id))->toArray();
|
$labels = $labels->merge(defaultLabels($this->application->id, $this->application->uuid, $this->pull_request_id))->toArray();
|
||||||
$docker_compose = [
|
$docker_compose = [
|
||||||
@ -906,6 +909,20 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
if ($this->server->isSwarm()) {
|
||||||
|
data_forget($docker_compose, 'services.' . $this->container_name . '.container_name');
|
||||||
|
data_forget($docker_compose, 'services.' . $this->container_name . '.expose');
|
||||||
|
data_forget($docker_compose, 'services.' . $this->container_name . '.restart');
|
||||||
|
|
||||||
|
data_forget($docker_compose, 'services.' . $this->container_name . '.mem_limit');
|
||||||
|
data_forget($docker_compose, 'services.' . $this->container_name . '.memswap_limit');
|
||||||
|
data_forget($docker_compose, 'services.' . $this->container_name . '.mem_swappiness');
|
||||||
|
data_forget($docker_compose, 'services.' . $this->container_name . '.mem_reservation');
|
||||||
|
data_forget($docker_compose, 'services.' . $this->container_name . '.cpus');
|
||||||
|
data_forget($docker_compose, 'services.' . $this->container_name . '.cpuset');
|
||||||
|
data_forget($docker_compose, 'services.' . $this->container_name . '.cpu_shares');
|
||||||
|
} else {
|
||||||
|
}
|
||||||
if ($this->server->isLogDrainEnabled() && $this->application->isLogDrainEnabled()) {
|
if ($this->server->isLogDrainEnabled() && $this->application->isLogDrainEnabled()) {
|
||||||
$docker_compose['services'][$this->container_name]['logging'] = [
|
$docker_compose['services'][$this->container_name]['logging'] = [
|
||||||
'driver' => 'fluentd',
|
'driver' => 'fluentd',
|
||||||
|
@ -67,7 +67,7 @@ class Server extends BaseModel
|
|||||||
{
|
{
|
||||||
$teamId = currentTeam()->id;
|
$teamId = currentTeam()->id;
|
||||||
$selectArray = collect($select)->concat(['id']);
|
$selectArray = collect($select)->concat(['id']);
|
||||||
return Server::whereTeamId($teamId)->with('settings')->select($selectArray->all())->orderBy('name');
|
return Server::whereTeamId($teamId)->with('settings','swarmDockers','standaloneDockers')->select($selectArray->all())->orderBy('name');
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function isUsable()
|
static public function isUsable()
|
||||||
@ -87,6 +87,8 @@ class Server extends BaseModel
|
|||||||
return $this->hasOne(ServerSetting::class);
|
return $this->hasOne(ServerSetting::class);
|
||||||
}
|
}
|
||||||
public function addInitialNetwork() {
|
public function addInitialNetwork() {
|
||||||
|
ray($this->id);
|
||||||
|
|
||||||
if ($this->id === 0) {
|
if ($this->id === 0) {
|
||||||
if ($this->isSwarm()) {
|
if ($this->isSwarm()) {
|
||||||
SwarmDocker::create([
|
SwarmDocker::create([
|
||||||
@ -106,13 +108,13 @@ class Server extends BaseModel
|
|||||||
} else {
|
} else {
|
||||||
if ($this->isSwarm()) {
|
if ($this->isSwarm()) {
|
||||||
SwarmDocker::create([
|
SwarmDocker::create([
|
||||||
'name' => 'coolify',
|
'name' => 'coolify-overlay',
|
||||||
'network' => 'coolify-overlay',
|
'network' => 'coolify-overlay',
|
||||||
'server_id' => $this->id,
|
'server_id' => $this->id,
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
StandaloneDocker::create([
|
StandaloneDocker::create([
|
||||||
'name' => 'coolify',
|
'name' => 'coolify-overlay',
|
||||||
'network' => 'coolify',
|
'network' => 'coolify',
|
||||||
'server_id' => $this->id,
|
'server_id' => $this->id,
|
||||||
]);
|
]);
|
||||||
@ -452,7 +454,7 @@ class Server extends BaseModel
|
|||||||
public function validateCoolifyNetwork($isSwarm = false)
|
public function validateCoolifyNetwork($isSwarm = false)
|
||||||
{
|
{
|
||||||
if ($isSwarm) {
|
if ($isSwarm) {
|
||||||
return instant_remote_process(["docker network create --driver overlay coolify-overlay >/dev/null 2>&1 || true"], $this, false);
|
return instant_remote_process(["docker network create --attachable --driver overlay coolify-overlay >/dev/null 2>&1 || true"], $this, false);
|
||||||
} else {
|
} else {
|
||||||
return instant_remote_process(["docker network create coolify --attachable >/dev/null 2>&1 || true"], $this, false);
|
return instant_remote_process(["docker network create coolify --attachable >/dev/null 2>&1 || true"], $this, false);
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,9 @@ function instant_remote_process(Collection|array $command, Server $server, $thro
|
|||||||
}
|
}
|
||||||
return excludeCertainErrors($process->errorOutput(), $exitCode);
|
return excludeCertainErrors($process->errorOutput(), $exitCode);
|
||||||
}
|
}
|
||||||
|
if ($output === 'null') {
|
||||||
|
$output = null;
|
||||||
|
}
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
function excludeCertainErrors(string $errorOutput, ?int $exitCode = null)
|
function excludeCertainErrors(string $errorOutput, ?int $exitCode = null)
|
||||||
|
@ -13,9 +13,9 @@ class SwarmDockerSeeder extends Seeder
|
|||||||
*/
|
*/
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
SwarmDocker::create([
|
// SwarmDocker::create([
|
||||||
'name' => 'Swarm Docker 1',
|
// 'name' => 'Swarm Docker 1',
|
||||||
'server_id' => 1,
|
// 'server_id' => 1,
|
||||||
]);
|
// ]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,21 +69,39 @@
|
|||||||
@endif
|
@endif
|
||||||
@if ($application->build_pack !== 'dockerimage' && $application->build_pack !== 'dockercompose')
|
@if ($application->build_pack !== 'dockerimage' && $application->build_pack !== 'dockercompose')
|
||||||
<h3>Docker Registry</h3>
|
<h3>Docker Registry</h3>
|
||||||
<div>Push the built image to a docker registry. More info <a class="underline"
|
@if ($application->destination->server->isSwarm())
|
||||||
href="https://coolify.io/docs/docker-registries" target="_blank">here</a>.</div>
|
<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>
|
||||||
|
@else
|
||||||
|
<div>Push the built image to a docker registry. More info <a class="underline"
|
||||||
|
href="https://coolify.io/docs/docker-registries" target="_blank">here</a>.</div>
|
||||||
|
@endif
|
||||||
<div class="flex flex-col gap-2 xl:flex-row">
|
<div class="flex flex-col gap-2 xl:flex-row">
|
||||||
@if ($application->build_pack === 'dockerimage')
|
@if ($application->build_pack === 'dockerimage')
|
||||||
<x-forms.input id="application.docker_registry_image_name" label="Docker Image" />
|
@if ($application->destination->server->isSwarm())
|
||||||
<x-forms.input id="application.docker_registry_image_tag" label="Docker Image Tag" />
|
<x-forms.input required id="application.docker_registry_image_name" label="Docker Image" />
|
||||||
|
<x-forms.input id="application.docker_registry_image_tag" label="Docker Image Tag" />
|
||||||
|
@else
|
||||||
|
<x-forms.input id="application.docker_registry_image_name" label="Docker Image" />
|
||||||
|
<x-forms.input id="application.docker_registry_image_tag" label="Docker Image Tag" />
|
||||||
|
@endif
|
||||||
@else
|
@else
|
||||||
<x-forms.input id="application.docker_registry_image_name"
|
@if ($application->destination->server->isSwarm())
|
||||||
helper="Empty means it won't push the image to a docker registry."
|
<x-forms.input id="application.docker_registry_image_name" required label="Docker Image" />
|
||||||
placeholder="Empty means it won't push the image to a docker registry."
|
<x-forms.input id="application.docker_registry_image_tag"
|
||||||
label="Docker Image" />
|
helper="If set, it will tag the built image with this tag too. <br><br>Example: If you set it to 'latest', it will push the image with the commit sha tag + with the latest tag."
|
||||||
<x-forms.input id="application.docker_registry_image_tag"
|
label="Docker Image Tag" />
|
||||||
placeholder="Empty means only push commit sha tag."
|
@else
|
||||||
helper="If set, it will tag the built image with this tag too. <br><br>Example: If you set it to 'latest', it will push the image with the commit sha tag + with the latest tag."
|
<x-forms.input id="application.docker_registry_image_name"
|
||||||
label="Docker Image Tag" />
|
helper="Empty means it won't push the image to a docker registry."
|
||||||
|
placeholder="Empty means it won't push the image to a docker registry."
|
||||||
|
label="Docker Image" />
|
||||||
|
<x-forms.input id="application.docker_registry_image_tag"
|
||||||
|
placeholder="Empty means only push commit sha tag."
|
||||||
|
helper="If set, it will tag the built image with this tag too. <br><br>Example: If you set it to 'latest', it will push the image with the commit sha tag + with the latest tag."
|
||||||
|
label="Docker Image Tag" />
|
||||||
|
@endif
|
||||||
|
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -140,8 +158,8 @@
|
|||||||
@endif
|
@endif
|
||||||
@if ($application->build_pack === 'dockercompose')
|
@if ($application->build_pack === 'dockercompose')
|
||||||
<x-forms.button wire:click="loadComposeFile">Reload Compose File</x-forms.button>
|
<x-forms.button wire:click="loadComposeFile">Reload Compose File</x-forms.button>
|
||||||
<x-forms.textarea rows="10" readonly id="application.docker_compose" label="Docker Compose Content"
|
<x-forms.textarea rows="10" readonly id="application.docker_compose"
|
||||||
helper="You need to modify the docker compose file." />
|
label="Docker Compose Content" helper="You need to modify the docker compose file." />
|
||||||
{{-- <x-forms.textarea rows="10" readonly id="application.docker_compose_pr"
|
{{-- <x-forms.textarea rows="10" readonly id="application.docker_compose_pr"
|
||||||
label="Docker PR Compose Content" helper="You need to modify the docker compose file." /> --}}
|
label="Docker PR Compose Content" helper="You need to modify the docker compose file." /> --}}
|
||||||
@endif
|
@endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user