guzzleClient = new Client(); } public function GetLatestDigestOfTag(string $name, string $tag) : ?string { $cacheKey = 'dockerhub-manifest-' . $name . $tag; $cachedVersion = apcu_fetch($cacheKey); if($cachedVersion !== false && is_string($cachedVersion)) { return $cachedVersion; } // 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' try { $authTokenRequest = $this->guzzleClient->request( 'GET', 'https://auth.docker.io/token?service=registry.docker.io&scope=repository:' . $name . ':pull' ); $body = $authTokenRequest->getBody()->getContents(); $decodedBody = json_decode($body, true); if(isset($decodedBody['token'])) { $authToken = $decodedBody['token']; $manifestRequest = $this->guzzleClient->request( 'HEAD', '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', 'Authorization' => 'Bearer ' . $authToken, ], ] ); $responseHeaders = $manifestRequest->getHeader('docker-content-digest'); if(count($responseHeaders) === 1) { $latestVersion = $responseHeaders[0]; apcu_add($cacheKey, $latestVersion, 600); return $latestVersion; } } error_log('Could not get digest of container ' . $name . ':' . $tag); return null; } catch (\Exception $e) { error_log('Could not get digest of container ' . $name . ':' . $tag . ' ' . $e->getMessage()); return null; } } }