Hello community, here is the log from the commit of package docker_1_12_6 for openSUSE:Factory checked in at 2018-01-09 14:55:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/docker_1_12_6 (Old) and /work/SRC/openSUSE:Factory/.docker_1_12_6.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "docker_1_12_6" Tue Jan 9 14:55:02 2018 rev:6 rq:562494 version:1.12.6 Changes: -------- --- /work/SRC/openSUSE:Factory/docker_1_12_6/docker_1_12_6.changes 2017-11-30 12:45:05.794561824 +0100 +++ /work/SRC/openSUSE:Factory/.docker_1_12_6.new/docker_1_12_6.changes 2018-01-09 14:55:07.322376841 +0100 @@ -1,0 +2,29 @@ +Thu Dec 21 12:21:06 UTC 2017 - [email protected] + +- Enable libseccomp for Docker package build, bsc#1072367 + +------------------------------------------------------------------- +Tue Dec 19 12:44:25 UTC 2017 - [email protected] + +- Add buildmode=pie for tests and binary build. bsc#1048046 bsc#1051429 + (similar as sr#514245 for docker package) + +------------------------------------------------------------------- +Mon Dec 18 10:32:36 UTC 2017 - [email protected] + +- Update private-registry mirroring patch to the newest version of the + upstream pull request (https://github.com/moby/moby/pull/34319) to + improve sanity and consistency checks. + * private-registry-0001-Add-private-registry-mirror-support.patch + +------------------------------------------------------------------- +Tue Dec 12 09:52:24 UTC 2017 - [email protected] + +- Update private-registry mirroring patch to reflect some feedback from + upstream and change the JSON config options to the Prefix/Mirrors one. + Notice that this patch is still subject to change until the final pull + request (https://github.com/moby/moby/pull/34319) is merged upstream. + + private-registry-0001-Implement-private-registry-mirror-support.patch + - private-registry-0001-Add-private-registry-mirror-support.patch + +------------------------------------------------------------------- @@ -30,0 +60 @@ + fix bsc#1074971 Old: ---- private-registry-0001-Implement-private-registry-mirror-support.patch New: ---- private-registry-0001-Add-private-registry-mirror-support.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ docker_1_12_6.spec ++++++ --- /var/tmp/diff_new_pack.lpjzRV/_old 2018-01-09 14:55:09.278285151 +0100 +++ /var/tmp/diff_new_pack.lpjzRV/_new 2018-01-09 14:55:09.278285151 +0100 @@ -95,14 +95,19 @@ # SUSE-BACKPORT: Patch fixing a DoS bug that makes certain operations fail on # a libdm device. bsc#1045628 Patch500: bsc1045628-0001-devicemapper-remove-container-rootfs-mountPath-after.patch -# SUSE-FEATURE: Add support to mirror non-upstream/private registries. -Patch600: private-registry-0001-Implement-private-registry-mirror-support.patch +# SUSE-FEATURE: Add support to mirror inofficial/private registries +# (https://github.com/moby/moby/pull/34319) +Patch600: private-registry-0001-Add-private-registry-mirror-support.patch BuildRequires: audit BuildRequires: bash-completion BuildRequires: device-mapper-devel >= 1.2.68 BuildRequires: glibc-devel-static BuildRequires: libapparmor-devel BuildRequires: libbtrfs-devel >= 3.8 +%define with_libseccomp 1 +%if 0%{?with_libseccomp} +BuildRequires: libseccomp-devel +%endif BuildRequires: procps BuildRequires: sqlite3-devel BuildRequires: systemd-devel @@ -248,7 +253,11 @@ (cat <<EOF export AUTO_GOPATH=1 export DOCKER_BUILDTAGS="exclude_graphdriver_aufs apparmor selinux" +%if 0%{?with_libseccomp} +export BUILDTAGS="seccomp $BUILDTAGS" +%endif export DOCKER_GITCOMMIT=%{git_version} +export BUILDFLAGS="-buildmode=pie" EOF ) > docker_build_env . ./docker_build_env @@ -262,6 +271,7 @@ # build the tests binary GOPATH=$(pwd)/vendor:$(pwd)/.gopath/ go test \ + -buildmode=pie \ -tags "$DOCKER_BUILDTAGS daemon autogen" \ -c github.com/docker/docker/integration-cli -o tests.main @@ -328,9 +338,12 @@ | grep -v 'github.com/docker/docker/cmd/dockerd$' \ | grep -v 'github.com/docker/docker/builder/dockerfile/parser$' \ | grep -v 'github.com/docker/docker/man$' \ +%if ! 0%{?with_libseccomp} + | grep -v 'github.com/docker/docker/profiles/seccomp$' \ +%endif | grep -v 'github.com/docker/docker/pkg/integration$') -go test -cover -ldflags -w -tags $EXCLUDE_TAGS -a -test.timeout=10m $PKG_LIST +go test -buildmode=pie -cover -ldflags -w -tags $EXCLUDE_TAGS -a -test.timeout=10m $PKG_LIST %endif %install ++++++ private-registry-0001-Add-private-registry-mirror-support.patch ++++++ >From cee4836847f76d3f7120489d17fa6e705da197a4 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg <[email protected]> Date: Fri, 28 Jul 2017 16:15:04 +0200 Subject: [PATCH] Add private-registry mirror support NOTE: This backport patch does NOT support the prefix semantics as described below. Instead, only the host of each prefix will be used. Therefore, there can only be one prefix for a given host. The daemon will panic in case more than one prefix point to the same host. Add support for mirroring private registries. The daemon.json config can now be configured as exemplified below: ```json { "registries": [ { "Prefix": "docker.io/alpine", "Mirrors": [ { "URL": "http://local-alpine-mirror.lan", } ] }, { "Prefix": "registry.suse.com", "Mirrors": [ { "URL": "https://remote.suse.mirror.com" } ] }, { "Prefix": "http://insecure.registry.org:5000" } ], "registry-mirrors": ["https://deprecated-mirror.com"] } ``` With the new semantics, a mirror will be selected as an endpoint if the specified prefix matches the prefix of the requested resource (e.g., an image reference). In the upper example, "local-alpine-mirror" will only serve as a mirror for docker.io if the requested resource matches the "alpine" prefix, such as "alpine:latest" or "alpine-foo/bar". Furthermore, private registries can now be mirrored as well. In the example above, "remote.suse.mirror.com" will serve as a mirror for all requests to "registry.suse.com". Notice that if no http{s,} scheme is specified, the URI will always default to https without fallback to http. An insecure registry can now be specified by adding the "http://" scheme to the corresponding prefix. Note that the configuration is sanity checked, so that a given mirror can serve multiple prefixes if they all point to the same registry, while a registry cannot simultaneously serve as a mirror. The daemon will warn in case the URI schemes of a registry and one of its mirrors do not correspond. This change deprecates the "insecure-regestries" and "registry-mirrors" options, while the "insecure-registries" cannot be used simultaneously with the new "registries", which doesn't allow a fallback from https to http for security reasons. Signed-off-by: Flavio Castelli <[email protected]> Signed-off-by: Valentin Rothberg <[email protected]> --- daemon/config.go | 4 + distribution/pull.go | 3 +- distribution/pull_v2.go | 2 +- integration-cli/docker_api_auth_test.go | 2 +- registry/config.go | 212 +++++++++++++++++++++++++++++++- registry/service_v2.go | 64 +++++++--- 6 files changed, 266 insertions(+), 21 deletions(-) diff --git a/daemon/config.go b/daemon/config.go index bf568efefa5c..3542d0508c45 100644 --- a/daemon/config.go +++ b/daemon/config.go @@ -340,6 +340,10 @@ func findConfigurationConflicts(config map[string]interface{}, flags *flag.FlagS // 1. Search keys from the file that we don't recognize as flags. unknownKeys := make(map[string]interface{}) for key, value := range config { + // skip config-only options (daemon.json) + if key == "registries" { + continue + } flagName := "-" + key if flag := flags.Lookup(flagName); flag == nil { unknownKeys[key] = value diff --git a/distribution/pull.go b/distribution/pull.go index dad93b656d65..707a918e8ae6 100644 --- a/distribution/pull.go +++ b/distribution/pull.go @@ -129,10 +129,11 @@ func Pull(ctx context.Context, ref reference.Named, imagePullConfig *ImagePullCo } } - logrus.Debugf("Trying to pull %s from %s %s", repoInfo.Name(), endpoint.URL, endpoint.Version) + logrus.Infof("Trying to pull %s from %s %s", repoInfo.Name(), endpoint.URL, endpoint.Version) puller, err := newPuller(endpoint, repoInfo, imagePullConfig) if err != nil { + logrus.Infof("Error pulling %s from %s %s: %v", repoInfo.Name(), endpoint.URL, endpoint.Version, err) lastErr = err continue } diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go index 5a786fba4bb5..f0d77245d4c8 100644 --- a/distribution/pull_v2.go +++ b/distribution/pull_v2.go @@ -371,7 +371,7 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat // the other side speaks the v2 protocol. p.confirmedV2 = true - logrus.Debugf("Pulling ref from V2 registry: %s", ref.String()) + logrus.Infof("Pulling ref %s from V2 registry %s", ref.String(), p.endpoint.URL) progress.Message(p.config.ProgressOutput, tagOrDigest, "Pulling from "+p.repo.Named().Name()) var ( diff --git a/integration-cli/docker_api_auth_test.go b/integration-cli/docker_api_auth_test.go index d73c61d4116f..7e9f64329a5f 100644 --- a/integration-cli/docker_api_auth_test.go +++ b/integration-cli/docker_api_auth_test.go @@ -16,7 +16,7 @@ func (s *DockerSuite) TestAuthApi(c *check.C) { Password: "no-password", } - expected := "Get https://registry-1.docker.io/v2/: unauthorized: incorrect username or password" + expected := "Get https://index.docker.io/v2/: unauthorized: incorrect username or password" status, body, err := sockRequest("POST", "/auth", config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusUnauthorized) diff --git a/registry/config.go b/registry/config.go index e349660e3261..d456abc2244c 100644 --- a/registry/config.go +++ b/registry/config.go @@ -11,9 +11,40 @@ import ( flag "github.com/docker/docker/pkg/mflag" "github.com/docker/docker/reference" registrytypes "github.com/docker/engine-api/types/registry" + "github.com/Sirupsen/logrus" ) -// ServiceOptions holds command line options. +// Registry holds information for a registry and its mirrors. +type Registry struct { + // Prefix is used for the lookup of endpoints, where the given registry + // is selected when its Prefix is a prefix of the passed reference, for + // instance, Prefix:"docker.io/opensuse" will match a `docker pull + // opensuse:tumleweed`. + Prefix string `json:"Prefix,omitempty"` + // The mirrors will be selected prior to the registry during lookup of + // endpoints. + Mirrors []Mirror `json:"Mirrors,omitempty"` + // Host is the host of the registry (e.g., "docker.io") + Host string + // This avoids to parse the URL of each new endpoint lookup. + URL *url.URL + // True if the host is "docker.io". + Official bool + // True if URL.Scheme == "https". + Secure bool +} + +// Mirror holds information for a given registry mirror. +type Mirror struct { + // Host is the URL specified by the user. At deamon start, the passed + // URL will be loaded into Mirror.URL and corresponding host stored in + // Mirror.Host. + Host string `json:"URL"` + // This avoids to parse the URL of each new endpoint lookup. + URL *url.URL +} + +// ServiceOptions holds the user-specified configuration options. type ServiceOptions struct { Mirrors []string `json:"registry-mirrors,omitempty"` InsecureRegistries []string `json:"insecure-registries,omitempty"` @@ -21,12 +52,18 @@ type ServiceOptions struct { // V2Only controls access to legacy registries. If it is set to true via the // command line flag the daemon will not attempt to contact v1 legacy registries V2Only bool `json:"disable-legacy-registry,omitempty"` + + // Registries holds information associated with the specified registries. + Registries []Registry `json:"registries,omitempty"` } // serviceConfig holds daemon configuration for the registry service. type serviceConfig struct { registrytypes.ServiceConfig V2Only bool + + // Registries holds information associated with the specified registries. + Registries map[string]Registry } var ( @@ -82,6 +119,13 @@ func (options *ServiceOptions) InstallCliFlags(cmd *flag.FlagSet, usageFn func(s // newServiceConfig returns a new instance of ServiceConfig func newServiceConfig(options ServiceOptions) *serviceConfig { + // The deprecated insecure-regitry flag conflicts with the semantics of + // the new Registries options, as they do NOT fallback to an insecure + // connection. + if len(options.InsecureRegistries) > 0 && len(options.Registries) > 0 { + panic("error: usage of \"registries\" with deprecated option \"insecure-registries\" is not supported") + } + // Localhost is by default considered as an insecure registry // This is a stop-gap for people who are running a private registry on localhost (especially on Boot2docker). // @@ -125,9 +169,175 @@ func newServiceConfig(options ServiceOptions) *serviceConfig { Official: true, } + if err := config.LoadRegistries(options.Registries); err != nil { + panic(fmt.Sprintf("[proxy path] Error loading registries: %s\n", err)) + } + + // Only print if registries are specified. This avoids some annoying + // logs from the client, which still shares code in this version of + // Docker. + if len(options.Registries) > 0 { + logrus.Infof("[proxy patch] loaded registries: %v", config.Registries) + } + return config } +// checkRegistries makes sure that no mirror serves more than one registry and +// that no host is used as a registry and as a mirror simultaneously. Notice +// that different registry prefixes can share a mirror as long as they point to +// the same registry. It also warns if the URI schemes of a given registry and +// one of its mirrors differ. +func (config *serviceConfig) checkRegistries() error { + inUse := make(map[string]string) // key: host, value: user + + // make sure that each mirror serves only one registry + for _, reg := range config.Registries { + for _, mirror := range reg.Mirrors { + if used, conflict := inUse[mirror.Host]; conflict { + if used != reg.URL.Host { + return fmt.Errorf("mirror '%s' can only serve one registry", mirror.Host) + } + } + inUse[mirror.Host] = reg.Host + // also warnf if seucurity levels differ + if reg.URL.Scheme != mirror.URL.Scheme { + logrus.Warnf("registry '%s' and mirror '%s' have different security levels", reg.URL, mirror.URL) + } + } + if reg.Secure && len(reg.Mirrors) == 0 { + logrus.Warnf("specifying secure registry '%s' without mirrors has no effect", reg.Prefix) + } + } + + // make sure that no registry host is used as a mirror + for _, reg := range config.Registries { + if _, conflict := inUse[reg.Host]; conflict { + return fmt.Errorf("registry '%s' cannot simultaneously serve as a mirror for '%s'", reg.URL.Host, inUse[reg.Host]) + } + } + return nil +} + +// FindRegistry returns a registry based on the passed reference. If more than +// one index-prefix match the reference, the longest index is returned. In +// case of no match, regFound is false. +func (config *serviceConfig) FindRegistry(reference string) (reg Registry, regFound bool) { + prefixStr := "" + prefixLen := 0 + for _, reg := range config.Registries { + if strings.HasPrefix(reference, reg.Prefix) { + length := len(reg.Prefix) + if length > prefixLen { + prefixStr = reg.Prefix + prefixLen = length + } + } + } + if prefixLen > 0 { + logrus.Debugf("[findRegistry] found registry %v for '%s'", config.Registries[prefixStr], reference) + return config.Registries[prefixStr], true + } + logrus.Debugf("[findRegistry] couldn't find registry for '%s'", reference) + return Registry{}, false +} + +// prepareMirror sets the corresponding data in mirror based on its host. +func prepareMirror(mirror *Mirror) error { + var err error + + if !strings.HasPrefix(mirror.Host, "http://") && !strings.HasPrefix(mirror.Host, "https://") { + mirror.Host = "https://" + mirror.Host + } + + mirror.Host, err = ValidateMirror(mirror.Host) + if err != nil { + return fmt.Errorf("invalid mirror: %s", err) + } + + mirror.URL, _ = url.Parse(mirror.Host) + mirror.Host = mirror.URL.Host // host:port + return nil +} + +// loadRegistry loads the specified registry into config.Registries, which is +// used for endpoint lookups. Notice that all sanity and consistency checks +// are deferred to config.checkRegistries(). +func (config *serviceConfig) loadRegistry(reg Registry) error { + if reg.Prefix == "" { + reg.Prefix = IndexName + } + reg.Prefix = strings.ToLower(reg.Prefix) + + // parse and set the URL of the registry + prefURL := reg.Prefix + if !strings.HasPrefix(reg.Prefix, "http://") && !strings.HasPrefix(reg.Prefix, "https://") { + prefURL = "https://" + prefURL + } + u, err := url.Parse(prefURL) + if err != nil { + return fmt.Errorf("cannot parse prefix '%s'", reg.Prefix) + } + // XXX: the host is used as the prefix + reg.Prefix = u.Host // host:port + reg.Host = u.Host // host:port + reg.URL = u + + if _, exists := config.Registries[reg.Prefix]; exists { + return fmt.Errorf("multiple prefixes pointing to host '%s': unsupported for this version of Docker", reg.Host) + } + + if reg.URL.Scheme == "https" { + reg.Secure = true + } + + if reg.URL.Host == IndexName || reg.URL.Host == DefaultNamespace { + reg.Official = true + } + + // validate and set mirrors + for i := range reg.Mirrors { + if err := prepareMirror(®.Mirrors[i]); err != nil { + return err + } + } + + config.Registries[reg.Prefix] = reg + + return nil +} + +// LoadRegistries loads the user-specified configuration options for registries. +func (config *serviceConfig) LoadRegistries(registries []Registry) error { + config.Registries = make(map[string]Registry) + + for _, reg := range registries { + if err := config.loadRegistry(reg); err != nil { + return err + } + } + + if len(config.Mirrors) > 0 { + mirrors := []Mirror{} + for _, host := range config.Mirrors { + mirror := Mirror{Host: host} + if err := prepareMirror(&mirror); err != nil { + return err + } + mirrors = append(mirrors, mirror) + } + if _, exists := config.Registries[IndexName]; !exists { + if err := config.loadRegistry(Registry{Prefix: IndexName}); err != nil { + return err + } + } + reg := config.Registries[IndexName] + reg.Mirrors = append(reg.Mirrors, mirrors...) + config.Registries[IndexName] = reg + } + return config.checkRegistries() +} + // isSecureIndex returns false if the provided indexName is part of the list of insecure registries // Insecure registries accept HTTP and/or accept HTTPS with certificates from unknown CAs. // diff --git a/registry/service_v2.go b/registry/service_v2.go index 5e62f8ff8c68..20cc8ce4c0c0 100644 --- a/registry/service_v2.go +++ b/registry/service_v2.go @@ -1,43 +1,73 @@ package registry import ( + "fmt" "net/url" "strings" "github.com/docker/go-connections/tlsconfig" + "github.com/Sirupsen/logrus" ) -func (s *DefaultService) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, err error) { +func (s *DefaultService) lookupV2Endpoints(reference string) (endpoints []APIEndpoint, err error) { var cfg = tlsconfig.ServerDefault tlsConfig := &cfg - if hostname == DefaultNamespace || hostname == DefaultV1Registry.Host { - // v2 mirrors - for _, mirror := range s.config.Mirrors { - if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") { - mirror = "https://" + mirror - } - mirrorURL, err := url.Parse(mirror) - if err != nil { - return nil, err + + logrus.Debugf("[lookupV2Endpoints] reference: %s", reference) + + // as the reference can be a prefix, extract the hostname with URL.Parse() + refURL := reference + if !strings.HasPrefix(refURL, "http://") && !strings.HasPrefix(refURL, "https://") { + refURL = "https://" + refURL + } + u, err := url.Parse(refURL) + if err != nil { + return nil, fmt.Errorf("[lookupV2Endpoints] error parsing reference %s: %s", reference, err) + } + + hostname := u.Host // hostname + port (if present) + if hostname == "" { + return nil, fmt.Errorf("[lookupV2Endpoints] cannot determine hostname of reference %s", reference) + } + + // create endpoints for official and configured registries + reg, foundReg := s.config.FindRegistry(reference) + official := false + if hostname == DefaultNamespace || hostname == IndexName || reg.Official { + official = true + } + if foundReg || official { + // set the URL of the registry + var endpointURL *url.URL + if official { + endpointURL = DefaultV2Registry + } else { + endpointURL = &url.URL{ + Scheme: reg.URL.Scheme, + Host: reg.URL.Host, } - mirrorTLSConfig, err := s.tlsConfigForMirror(mirrorURL) + } + + // if present, add mirrors before the registry + for _, mirror := range reg.Mirrors { + mirrorTLSConfig, err := s.tlsConfigForMirror(mirror.URL) if err != nil { - return nil, err + return nil, fmt.Errorf("[lookupV2Endpoints] %s", err) } endpoints = append(endpoints, APIEndpoint{ - URL: mirrorURL, - // guess mirrors are v2 + URL: mirror.URL, Version: APIVersion2, Mirror: true, TrimHostname: true, TLSConfig: mirrorTLSConfig, }) } - // v2 registry + + // add the registry endpoints = append(endpoints, APIEndpoint{ - URL: DefaultV2Registry, + URL: endpointURL, Version: APIVersion2, - Official: true, + Official: official, TrimHostname: true, TLSConfig: tlsConfig, }) -- 2.13.6
