From fedb0a65dfb8a353d181aa0fdd3fb593d598b692 Mon Sep 17 00:00:00 2001 From: lonode <32384862+lonode@users.noreply.github.com> Date: Wed, 13 May 2026 14:22:19 +0200 Subject: [PATCH 1/4] Add support for library (official) images Signed-off-by: lonode <32384862+lonode@users.noreply.github.com> --- php/src/Docker/DockerHubManager.php | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/php/src/Docker/DockerHubManager.php b/php/src/Docker/DockerHubManager.php index c11d81eb..097c7521 100644 --- a/php/src/Docker/DockerHubManager.php +++ b/php/src/Docker/DockerHubManager.php @@ -3,8 +3,6 @@ declare(strict_types=1); namespace AIO\Docker; -use AIO\ContainerDefinitionFetcher; -use AIO\Data\ConfigurationManager; use GuzzleHttp\Client; readonly class DockerHubManager { @@ -15,6 +13,16 @@ readonly class DockerHubManager { $this->guzzleClient = new Client(); } + + // Official Docker Hub images need the library/ prefix when using the registry API directly. + private function NormalizeImageName(string $name): string { + if (!str_contains($name, '/')) { + return 'library/' . $name; + } + return $name; + } + + public function GetLatestDigestOfTag(string $name, string $tag) : ?string { $cacheKey = 'dockerhub-manifest-' . $name . $tag; @@ -24,11 +32,12 @@ readonly class DockerHubManager { } // If one of the links below should ever become outdated, we can still upgrade the mastercontainer via the webinterface manually by opening '/api/docker/getwatchtower' + $normalizedName = $this->NormalizeImageName($name); try { $authTokenRequest = $this->guzzleClient->request( 'GET', - 'https://auth.docker.io/token?service=registry.docker.io&scope=repository:' . $name . ':pull' + 'https://auth.docker.io/token?service=registry.docker.io&scope=repository:' . $normalizedName . ':pull' ); $body = $authTokenRequest->getBody()->getContents(); $decodedBody = json_decode($body, true, 512, JSON_THROW_ON_ERROR); @@ -36,7 +45,7 @@ readonly class DockerHubManager { $authToken = $decodedBody['token']; $manifestRequest = $this->guzzleClient->request( 'HEAD', - 'https://registry-1.docker.io/v2/'.$name.'/manifests/' . $tag, + 'https://registry-1.docker.io/v2/'.$normalizedName.'/manifests/' . $tag, [ 'headers' => [ 'Accept' => 'application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.docker.distribution.manifest.v2+json', @@ -52,10 +61,10 @@ readonly class DockerHubManager { } } - error_log('Could not get digest of container ' . $name . ':' . $tag); + error_log('Could not get digest of container ' . $normalizedName . ':' . $tag); return null; } catch (\Exception $e) { - error_log('Could not get digest of container ' . $name . ':' . $tag . ' ' . $e->getMessage()); + error_log('Could not get digest of container ' . $normalizedName . ':' . $tag . ' ' . $e->getMessage()); return null; } } From ff7443b566cadc5a637e979a61c6bb7a2002a781 Mon Sep 17 00:00:00 2001 From: lonode <32384862+lonode@users.noreply.github.com> Date: Wed, 13 May 2026 14:22:36 +0200 Subject: [PATCH 2/4] add support for multicontainer on community containers Signed-off-by: lonode <32384862+lonode@users.noreply.github.com> --- php/src/ContainerDefinitionFetcher.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/php/src/ContainerDefinitionFetcher.php b/php/src/ContainerDefinitionFetcher.php index e4625a24..9854655e 100644 --- a/php/src/ContainerDefinitionFetcher.php +++ b/php/src/ContainerDefinitionFetcher.php @@ -52,14 +52,18 @@ readonly class ContainerDefinitionFetcher { $standardContainerNames = array_column($data['aio_services_v1'], 'container_name'); $additionalContainerNames = []; + $additionalTopLevelContainerNames = []; foreach ($this->configurationManager->aioCommunityContainers as $communityContainer) { if ($communityContainer !== '') { $path = DataConst::GetCommunityContainersDirectory() . '/' . $communityContainer . '/' . $communityContainer . '.json'; $additionalData = json_decode((string)file_get_contents($path), true, 512, JSON_THROW_ON_ERROR); $data = array_merge_recursive($data, $additionalData); + foreach ($additionalData['aio_services_v1'] as $additionalEntry) { + $additionalContainerNames[] = $additionalEntry['container_name']; + } if (isset($additionalData['aio_services_v1'][0]['display_name']) && $additionalData['aio_services_v1'][0]['display_name'] !== '') { - // Store container_name of community containers in variable for later - $additionalContainerNames[] = $additionalData['aio_services_v1'][0]['container_name']; + // Store main container_name of community containers in variable for later + $additionalTopLevelContainerNames[] = $additionalData['aio_services_v1'][0]['container_name']; } } } @@ -176,7 +180,7 @@ readonly class ContainerDefinitionFetcher { if ($entry['container_name'] === 'nextcloud-aio-apache') { // Add community containers first and default ones last so that aio_variables works correctly $valueDependsOnTemp = []; - foreach ($additionalContainerNames as $containerName) { + foreach ($additionalTopLevelContainerNames as $containerName) { $valueDependsOnTemp[] = $containerName; } $valueDependsOn = array_merge_recursive($valueDependsOnTemp, $valueDependsOn); From 3517ba3039d1d40e8d0cf767e8a670935a75edec Mon Sep 17 00:00:00 2001 From: lonode <32384862+lonode@users.noreply.github.com> Date: Tue, 19 May 2026 15:13:51 +0200 Subject: [PATCH 3/4] apply suggestion Signed-off-by: lonode <32384862+lonode@users.noreply.github.com> --- php/src/Docker/DockerHubManager.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/php/src/Docker/DockerHubManager.php b/php/src/Docker/DockerHubManager.php index 097c7521..db718cff 100644 --- a/php/src/Docker/DockerHubManager.php +++ b/php/src/Docker/DockerHubManager.php @@ -32,12 +32,12 @@ readonly class DockerHubManager { } // If one of the links below should ever become outdated, we can still upgrade the mastercontainer via the webinterface manually by opening '/api/docker/getwatchtower' - $normalizedName = $this->NormalizeImageName($name); + $name = $this->NormalizeImageName($name); try { $authTokenRequest = $this->guzzleClient->request( 'GET', - 'https://auth.docker.io/token?service=registry.docker.io&scope=repository:' . $normalizedName . ':pull' + 'https://auth.docker.io/token?service=registry.docker.io&scope=repository:' . $name . ':pull' ); $body = $authTokenRequest->getBody()->getContents(); $decodedBody = json_decode($body, true, 512, JSON_THROW_ON_ERROR); @@ -45,7 +45,7 @@ readonly class DockerHubManager { $authToken = $decodedBody['token']; $manifestRequest = $this->guzzleClient->request( 'HEAD', - 'https://registry-1.docker.io/v2/'.$normalizedName.'/manifests/' . $tag, + 'https://registry-1.docker.io/v2/'.$name.'/manifests/' . $tag, [ 'headers' => [ 'Accept' => 'application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.docker.distribution.manifest.v2+json', @@ -61,10 +61,10 @@ readonly class DockerHubManager { } } - error_log('Could not get digest of container ' . $normalizedName . ':' . $tag); + error_log('Could not get digest of container ' . $name . ':' . $tag); return null; } catch (\Exception $e) { - error_log('Could not get digest of container ' . $normalizedName . ':' . $tag . ' ' . $e->getMessage()); + error_log('Could not get digest of container ' . $name . ':' . $tag . ' ' . $e->getMessage()); return null; } } From abaea7b4c2159d02ffcd9b8f19b6f7941e55c92c Mon Sep 17 00:00:00 2001 From: lonode <32384862+lonode@users.noreply.github.com> Date: Thu, 21 May 2026 17:42:21 +0200 Subject: [PATCH 4/4] change case Signed-off-by: lonode <32384862+lonode@users.noreply.github.com> --- php/src/Docker/DockerHubManager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php/src/Docker/DockerHubManager.php b/php/src/Docker/DockerHubManager.php index db718cff..a7d35ed7 100644 --- a/php/src/Docker/DockerHubManager.php +++ b/php/src/Docker/DockerHubManager.php @@ -15,7 +15,7 @@ readonly class DockerHubManager { // Official Docker Hub images need the library/ prefix when using the registry API directly. - private function NormalizeImageName(string $name): string { + private function normalizeImageName(string $name): string { if (!str_contains($name, '/')) { return 'library/' . $name; } @@ -32,7 +32,7 @@ readonly class DockerHubManager { } // If one of the links below should ever become outdated, we can still upgrade the mastercontainer via the webinterface manually by opening '/api/docker/getwatchtower' - $name = $this->NormalizeImageName($name); + $name = $this->normalizeImageName($name); try { $authTokenRequest = $this->guzzleClient->request(