Skip to content

Commit c662cbb

Browse files
committed
pkg/compose: simplify getting auth-config key
Rewrite to remove the `github.com/docker/docker/registry` dependency, which will not be included in the upcoming "api" and "client" modules, and will not be a public package in the module used for the daemon itself. 1. don't call "/info" API endpoint to get default registry The `IndexServerAddress` in the `/info` endpoint was added as part of the initial Windows implementation of the engine. For legal reasons, Microsoft Windows (and thus Docker images based on Windows) were not allowed to be distributed through non-Microsoft infrastructure. As a temporary solution, a dedicated "registry-win-tp3.docker.io" registry was created to serve Windows images. Using separate registries was not an ideal solution, and a more permanent solution was created by introducing "foreign image layers" in the distribution spec, after which the "registry-win-tp3.docker.io" ceased to exist, and removed from the engine through docker/docker PR 21100. However, the `ElectAuthServer` was left in place, quoting from that PR; > make the client check which default registry the daemon uses is still > more correct than leaving it up to the client, even if it won't technically > matter after this PR. There may be some backward compatibility scenarios > where `ElectAuthServer` [sic] is still helpful. That comment was 10 Years ago, and the CLI stopped using this information, as the default registry is not configurable, so in practice was a static value. (see docker/cli@b4ca1c7). 2. replace `ParseRepositoryInfo` and `GetAuthConfigKey` with local impl The `ParseRepositoryInfo` function was originally implemented for use by the daemon itself. It returns a `RepositoryInfo` struct that holds information about the repository and the registry the repository can be found in. As it was written for use by the daemon, it also was designed to be used in combination with the daemon's configuration (such as mirrors, and insecure registries). If no daemon configuration is present, which would be the case when used in a CLI, it uses fallback logic as used in the daemon to detect if the registry is running on a localhost / loopback address, because such addresses are allowed to be "insecure" by default; this includes resolving the IP-address of the host (if it's not an IP-address). Unfortunately, these functions (and related types) were reused in the CLI and many other places, which resulted in those types to be deeply ingrained in interfaces and (external) code. For compose; it was only used to get the "auth-config key" to use for looking up auth information from the credentials store, which still needs special handling for the "default" (docker hub) domain, which unlike other image references doesn't use the hostname included in the image reference for the actual registry (and key for storing auth). For those that want to follow along; First, note that `GetAuthConfig` only requires a `registry.IndexInfo`, so not the whole `RepositoryInfo` struct; https://github.com/moby/moby/blob/v28.3.3/registry/types.go#L8-L24 From the `registry.IndexInfo` it only uses the `IsOfficial` and `Name` fields; https://github.com/moby/moby/blob/v28.3.3/registry/config.go#L390-L395 But to get the `IndexInfo`, `ParseRepositoryInfo` is needed, which first takes the image reference's "domain name" (e.g. `docker.io`); https://github.com/moby/moby/blob/v28.3.3/registry/config.go#L421 This gets "normalized" for some cases where the `info.IndexServerAddress` was incorrectly assumed to be the canonical domain for Docker Hub registry, and which _does_ happen to also be accessible as a "v2" registry. https://github.com/moby/moby/blob/v28.3.3/registry/config.go#L334-L341 After normalizing, it checks if it's a docker hub address ("docker.io" after normalizing); Docker Hub is always required to use a secure connection, so no detection happens, and the `Official` field is set to indicate it's Docker Hub (this code path was already simplified as historically it would try to find daemon configuration (or otherwise use a default) for Mirror configuration; https://github.com/moby/moby/blob/v28.3.3/registry/config.go#L420-L443 For non-Docker Hub registries, it also sets the name, and attempts to detect if the registry is allowed to be "insecure"; https://github.com/moby/moby/blob/v28.3.3/registry/config.go#L435-L442 Which (as mentioned) involves parsing the address and, if needed, resolving the hostname https://github.com/moby/moby/blob/v28.3.3/registry/config.go#L445-L481 As `Insecure` is not used for looking up the auth-config key, all of the above can be reduced to; - Is the hostname obtained from the image reference "docker.io" (after normalizing)? - If so, use the special `https://index.docker.io/v1/` as auth-config key (another horrible remnant) - Otherwise use the hostname obtained from the image reference as-is Signed-off-by: Sebastiaan van Stijn <[email protected]>
1 parent 0dc9852 commit c662cbb

File tree

3 files changed

+30
-30
lines changed

3 files changed

+30
-30
lines changed

internal/registry/registry.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package registry
2+
3+
import (
4+
"github.com/distribution/reference"
5+
)
6+
7+
const (
8+
// IndexHostname is the index hostname, used for authentication and image search.
9+
IndexHostname = "index.docker.io"
10+
// IndexServer is used for user auth and image search
11+
IndexServer = "https://index.docker.io/v1/"
12+
// IndexName is the name of the index
13+
IndexName = "docker.io"
14+
)
15+
16+
// GetAuthConfigKey special-cases using the full index address of the official
17+
// index as the AuthConfig key, and uses the (host)name[:port] for private indexes.
18+
func GetAuthConfigKey(reposName reference.Named) string {
19+
indexName := reference.Domain(reposName)
20+
if indexName == IndexName || indexName == IndexHostname {
21+
return IndexServer
22+
}
23+
return indexName
24+
}

pkg/compose/pull.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ import (
3434
"github.com/docker/docker/api/types/image"
3535
"github.com/docker/docker/client"
3636
"github.com/docker/docker/pkg/jsonmessage"
37-
"github.com/docker/docker/registry"
3837
"github.com/hashicorp/go-multierror"
3938
"github.com/opencontainers/go-digest"
4039
"golang.org/x/sync/errgroup"
4140

41+
"github.com/docker/compose/v2/internal/registry"
4242
"github.com/docker/compose/v2/pkg/api"
4343
"github.com/docker/compose/v2/pkg/progress"
4444
)
@@ -281,13 +281,7 @@ func ImageDigestResolver(ctx context.Context, file *configfile.ConfigFile, apiCl
281281
}
282282

283283
func encodedAuth(ref reference.Named, configFile driver.Auth) (string, error) {
284-
repoInfo, err := registry.ParseRepositoryInfo(ref)
285-
if err != nil {
286-
return "", err
287-
}
288-
289-
key := registry.GetAuthConfigKey(repoInfo.Index)
290-
authConfig, err := configFile.GetAuthConfig(key)
284+
authConfig, err := configFile.GetAuthConfig(registry.GetAuthConfigKey(ref))
291285
if err != nil {
292286
return "", err
293287
}

pkg/compose/push.go

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,10 @@ import (
2929
"github.com/distribution/reference"
3030
"github.com/docker/buildx/driver"
3131
"github.com/docker/docker/api/types/image"
32-
"github.com/docker/docker/api/types/system"
3332
"github.com/docker/docker/pkg/jsonmessage"
34-
"github.com/docker/docker/registry"
3533
"golang.org/x/sync/errgroup"
3634

35+
"github.com/docker/compose/v2/internal/registry"
3736
"github.com/docker/compose/v2/pkg/api"
3837
"github.com/docker/compose/v2/pkg/progress"
3938
)
@@ -51,14 +50,6 @@ func (s *composeService) push(ctx context.Context, project *types.Project, optio
5150
eg, ctx := errgroup.WithContext(ctx)
5251
eg.SetLimit(s.maxConcurrency)
5352

54-
info, err := s.apiClient().Info(ctx)
55-
if err != nil {
56-
return err
57-
}
58-
if info.IndexServerAddress == "" {
59-
info.IndexServerAddress = registry.IndexServer
60-
}
61-
6253
w := progress.ContextWriter(ctx)
6354
for _, service := range project.Services {
6455
if service.Build == nil || service.Image == "" {
@@ -79,7 +70,7 @@ func (s *composeService) push(ctx context.Context, project *types.Project, optio
7970

8071
for _, tag := range tags {
8172
eg.Go(func() error {
82-
err := s.pushServiceImage(ctx, tag, info, s.configFile(), w, options.Quiet)
73+
err := s.pushServiceImage(ctx, tag, s.configFile(), w, options.Quiet)
8374
if err != nil {
8475
if !options.IgnoreFailures {
8576
return err
@@ -93,22 +84,13 @@ func (s *composeService) push(ctx context.Context, project *types.Project, optio
9384
return eg.Wait()
9485
}
9586

96-
func (s *composeService) pushServiceImage(ctx context.Context, tag string, info system.Info, configFile driver.Auth, w progress.Writer, quietPush bool) error {
87+
func (s *composeService) pushServiceImage(ctx context.Context, tag string, configFile driver.Auth, w progress.Writer, quietPush bool) error {
9788
ref, err := reference.ParseNormalizedNamed(tag)
9889
if err != nil {
9990
return err
10091
}
10192

102-
repoInfo, err := registry.ParseRepositoryInfo(ref)
103-
if err != nil {
104-
return err
105-
}
106-
107-
key := repoInfo.Index.Name
108-
if repoInfo.Index.Official {
109-
key = info.IndexServerAddress
110-
}
111-
authConfig, err := configFile.GetAuthConfig(key)
93+
authConfig, err := configFile.GetAuthConfig(registry.GetAuthConfigKey(ref))
11294
if err != nil {
11395
return err
11496
}

0 commit comments

Comments
 (0)