mirror of
https://github.com/coollabsio/coolify.git
synced 2026-09-28 02:06:37 -04:00
fix(domains): route Compose domains using service ports
Resolve routing ports per Compose service, preserve legacy embedded ports, and ignore non-TCP declarations.
This commit is contained in:
@@ -607,6 +607,13 @@ function firstDockerComposeServicePort(mixed $service): ?int
|
||||
->merge(data_get($service, 'ports', []));
|
||||
|
||||
foreach ($portDefinitions as $definition) {
|
||||
$protocol = is_array($definition)
|
||||
? data_get($definition, 'protocol', 'tcp')
|
||||
: (str_contains((string) $definition, '/') ? str((string) $definition)->afterLast('/')->value() : 'tcp');
|
||||
if ($protocol !== 'tcp') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$port = is_array($definition)
|
||||
? data_get($definition, 'target')
|
||||
: str((string) $definition)->before('/')->afterLast(':')->value();
|
||||
@@ -620,18 +627,29 @@ function firstDockerComposeServicePort(mixed $service): ?int
|
||||
}
|
||||
|
||||
function dockerComposeServicePort(?string $compose, ?string $serviceName): ?int
|
||||
{
|
||||
return dockerComposeServicePorts($compose, $serviceName)[0] ?? null;
|
||||
}
|
||||
|
||||
function dockerComposeServicePorts(?string $compose, ?string $serviceName): array
|
||||
{
|
||||
if (blank($compose) || blank($serviceName)) {
|
||||
return null;
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
$services = data_get(Yaml::parse($compose), 'services', []);
|
||||
} catch (Throwable) {
|
||||
return null;
|
||||
return [];
|
||||
}
|
||||
|
||||
return firstDockerComposeServicePort(is_array($services) ? ($services[$serviceName] ?? null) : null);
|
||||
$service = is_array($services) ? ($services[$serviceName] ?? []) : [];
|
||||
|
||||
return collect(data_get($service, 'expose', []))
|
||||
->merge(data_get($service, 'ports', []))
|
||||
->map(fn ($definition) => firstDockerComposeServicePort(['expose' => [$definition]]))
|
||||
->filter(fn ($port) => $port !== null)
|
||||
->unique()->values()->all();
|
||||
}
|
||||
|
||||
function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null, bool $generate_unique_uuid = false, ?string $image = null, string $redirect_direction = 'both', bool $is_http_basic_auth_enabled = false, ?string $http_basic_auth_username = null, ?string $http_basic_auth_password = null, ?Collection $noindex_domains = null, bool $escape_redirect_replacement_for_compose = true, array $domainPortOverrides = [])
|
||||
|
||||
@@ -390,9 +390,6 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
|
||||
return collect([]);
|
||||
}
|
||||
$services = data_get($yaml, 'services', collect([]));
|
||||
$applicationServiceCount = collect($services)
|
||||
->reject(fn (mixed $service): bool => isDatabaseImage(data_get($service, 'image')))
|
||||
->count();
|
||||
$topLevel = collect([
|
||||
'volumes' => collect(data_get($yaml, 'volumes', [])),
|
||||
'networks' => collect(data_get($yaml, 'networks', [])),
|
||||
@@ -1357,9 +1354,7 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
|
||||
$domainPortOverrides = $isPullRequest
|
||||
? ($previewForPorts?->domain_port_overrides ?? [])
|
||||
: ($originalResource->domain_port_overrides ?? []);
|
||||
$exposedPorts = $originalResource->settings->is_static ? [80] : $originalResource->ports_exposes_array;
|
||||
$onlyPort = firstDockerComposeServicePort($service)
|
||||
?? ($applicationServiceCount === 1 ? ($exposedPorts[0] ?? null) : null);
|
||||
$onlyPort = firstDockerComposeServicePort($service);
|
||||
if (! $use_network_mode && (! $shouldGenerateLabelsExactly || $server->proxyType() === ProxyTypes::TRAEFIK->value)) {
|
||||
$serviceLabels = addTraefikDockerNetworkLabel($serviceLabels, $baseNetwork->first());
|
||||
}
|
||||
@@ -1566,7 +1561,6 @@ function serviceParser(Service $resource): Collection
|
||||
$envComments = extractYamlEnvironmentComments($compose);
|
||||
|
||||
$server = data_get($resource, 'server');
|
||||
$allServices = get_service_templates();
|
||||
|
||||
try {
|
||||
$yaml = Yaml::parse($compose);
|
||||
@@ -1699,22 +1693,7 @@ function serviceParser(Service $resource): Collection
|
||||
|
||||
$containerName = "$serviceName-{$resource->uuid}";
|
||||
|
||||
if ($serviceName === 'registry') {
|
||||
$tempServiceName = 'docker-registry';
|
||||
} else {
|
||||
$tempServiceName = $serviceName;
|
||||
}
|
||||
if (str(data_get($service, 'image'))->contains('glitchtip')) {
|
||||
$tempServiceName = 'glitchtip';
|
||||
}
|
||||
if ($serviceName === 'supabase-kong') {
|
||||
$tempServiceName = 'supabase';
|
||||
}
|
||||
$serviceDefinition = data_get($allServices, $tempServiceName);
|
||||
$predefinedPort = data_get($serviceDefinition, 'port');
|
||||
if ($serviceName === 'plausible') {
|
||||
$predefinedPort = '8000';
|
||||
}
|
||||
$predefinedPort = $resource->getRequiredPort();
|
||||
|
||||
if ($migratedApp || $migratedDb) {
|
||||
// Use the already determined migrated service
|
||||
@@ -2084,22 +2063,7 @@ function serviceParser(Service $resource): Collection
|
||||
|
||||
$containerName = "$serviceName-{$resource->uuid}";
|
||||
|
||||
if ($serviceName === 'registry') {
|
||||
$tempServiceName = 'docker-registry';
|
||||
} else {
|
||||
$tempServiceName = $serviceName;
|
||||
}
|
||||
if (str(data_get($service, 'image'))->contains('glitchtip')) {
|
||||
$tempServiceName = 'glitchtip';
|
||||
}
|
||||
if ($serviceName === 'supabase-kong') {
|
||||
$tempServiceName = 'supabase';
|
||||
}
|
||||
$serviceDefinition = data_get($allServices, $tempServiceName);
|
||||
$predefinedPort = data_get($serviceDefinition, 'port');
|
||||
if ($serviceName === 'plausible') {
|
||||
$predefinedPort = '8000';
|
||||
}
|
||||
$predefinedPort = $resource->getRequiredPort();
|
||||
|
||||
if ($migratedApp || $migratedDb) {
|
||||
// Use the already determined migrated service
|
||||
@@ -2642,7 +2606,7 @@ function serviceParser(Service $resource): Collection
|
||||
? data_get($originalResource, 'redirect')
|
||||
: 'both';
|
||||
$onlyPort = $originalResource instanceof ServiceApplication
|
||||
? ($originalResource->getRequiredPort() ?? $predefinedPort)
|
||||
? $originalResource->getRequiredPort()
|
||||
: $predefinedPort;
|
||||
if (! $use_network_mode && (! $shouldGenerateLabelsExactly || $server->proxyType() === ProxyTypes::TRAEFIK->value)) {
|
||||
$serviceLabels = addTraefikDockerNetworkLabel($serviceLabels, $baseNetwork->first());
|
||||
@@ -2677,7 +2641,7 @@ function serviceParser(Service $resource): Collection
|
||||
service_name: $serviceName,
|
||||
image: $image,
|
||||
onlyPort: $onlyPort,
|
||||
predefinedPort: $predefinedPort,
|
||||
predefinedPort: $onlyPort,
|
||||
domainPortOverrides: $originalResource->domain_port_overrides ?? [],
|
||||
noindex_domains: $noindexDomains,
|
||||
redirect_direction: $redirectDirection
|
||||
@@ -2710,7 +2674,7 @@ function serviceParser(Service $resource): Collection
|
||||
service_name: $serviceName,
|
||||
image: $image,
|
||||
onlyPort: $onlyPort,
|
||||
predefinedPort: $predefinedPort,
|
||||
predefinedPort: $onlyPort,
|
||||
domainPortOverrides: $originalResource->domain_port_overrides ?? [],
|
||||
noindex_domains: $noindexDomains,
|
||||
redirect_direction: $redirectDirection
|
||||
|
||||
@@ -2486,7 +2486,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
} catch (Exception $e) {
|
||||
throw new RuntimeException($e->getMessage());
|
||||
}
|
||||
$allServices = get_service_templates();
|
||||
$topLevelVolumes = collect(data_get($yaml, 'volumes', []));
|
||||
$topLevelNetworks = collect(data_get($yaml, 'networks', []));
|
||||
$topLevelConfigs = collect(data_get($yaml, 'configs', []));
|
||||
@@ -2512,25 +2511,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
}
|
||||
$topLevelVolumes = collect($tempTopLevelVolumes);
|
||||
}
|
||||
$services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $resource, $allServices, $envComments) {
|
||||
// Workarounds for beta users.
|
||||
if ($serviceName === 'registry') {
|
||||
$tempServiceName = 'docker-registry';
|
||||
} else {
|
||||
$tempServiceName = $serviceName;
|
||||
}
|
||||
if (str(data_get($service, 'image'))->contains('glitchtip')) {
|
||||
$tempServiceName = 'glitchtip';
|
||||
}
|
||||
if ($serviceName === 'supabase-kong') {
|
||||
$tempServiceName = 'supabase';
|
||||
}
|
||||
$serviceDefinition = data_get($allServices, $tempServiceName);
|
||||
$predefinedPort = data_get($serviceDefinition, 'port');
|
||||
if ($serviceName === 'plausible') {
|
||||
$predefinedPort = '8000';
|
||||
}
|
||||
// End of workarounds for beta users.
|
||||
$services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $resource, $envComments) {
|
||||
$predefinedPort = $resource->getRequiredPort();
|
||||
$serviceVolumes = collect(data_get($service, 'volumes', []));
|
||||
$servicePorts = collect(data_get($service, 'ports', []));
|
||||
$serviceNetworks = collect(data_get($service, 'networks', []));
|
||||
@@ -3107,7 +3089,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
? ($savedService->domain_port_overrides ?? [])
|
||||
: [];
|
||||
$onlyPort = $savedService instanceof ServiceApplication
|
||||
? ($savedService->getRequiredPort() ?? $predefinedPort)
|
||||
? $savedService->getRequiredPort()
|
||||
: $predefinedPort;
|
||||
if ($shouldGenerateLabelsExactly) {
|
||||
switch ($resource->server->proxyType()) {
|
||||
@@ -3139,7 +3121,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
service_name: $serviceName,
|
||||
image: data_get($service, 'image'),
|
||||
onlyPort: $onlyPort,
|
||||
predefinedPort: $predefinedPort,
|
||||
predefinedPort: $onlyPort,
|
||||
noindex_domains: $noindexDomains,
|
||||
redirect_direction: $redirectDirection,
|
||||
domainPortOverrides: $domainPortOverrides,
|
||||
@@ -3172,7 +3154,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
service_name: $serviceName,
|
||||
image: data_get($service, 'image'),
|
||||
onlyPort: $onlyPort,
|
||||
predefinedPort: $predefinedPort,
|
||||
predefinedPort: $onlyPort,
|
||||
noindex_domains: $noindexDomains,
|
||||
redirect_direction: $redirectDirection,
|
||||
domainPortOverrides: $domainPortOverrides,
|
||||
@@ -3318,10 +3300,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
if ($pull_request_id !== 0) {
|
||||
$definedNetwork = collect(["{$resource->uuid}-$pull_request_id"]);
|
||||
}
|
||||
$usesSharedApplicationPort = collect($services)
|
||||
->reject(fn (mixed $service): bool => isDatabaseImage(data_get($service, 'image')))
|
||||
->count() === 1;
|
||||
$services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $resource, $server, $pull_request_id, $preview_id, $usesSharedApplicationPort) {
|
||||
$services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $resource, $server, $pull_request_id, $preview_id) {
|
||||
$serviceVolumes = collect(data_get($service, 'volumes', []));
|
||||
$servicePorts = collect(data_get($service, 'ports', []));
|
||||
$serviceNetworks = collect(data_get($service, 'networks', []));
|
||||
@@ -3918,9 +3897,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
$domainPortOverrides = $pull_request_id === 0
|
||||
? ($resource->domain_port_overrides ?? [])
|
||||
: ($preview?->domain_port_overrides ?? []);
|
||||
$exposedPorts = $resource->settings->is_static ? [80] : $resource->ports_exposes_array;
|
||||
$onlyPort = firstDockerComposeServicePort($service)
|
||||
?? ($usesSharedApplicationPort ? ($exposedPorts[0] ?? null) : null);
|
||||
$onlyPort = firstDockerComposeServicePort($service);
|
||||
if ($shouldGenerateLabelsExactly) {
|
||||
switch ($server->proxyType()) {
|
||||
case ProxyTypes::TRAEFIK->value:
|
||||
|
||||
Reference in New Issue
Block a user