docker: add patches

Signed-off-by: Grooooot <isula@huawei.com>
This commit is contained in:
Grooooot 2020-03-05 14:48:59 +08:00
parent be56a4fe89
commit e7de2c79b3
12 changed files with 5698 additions and 1 deletions

View File

@ -1,6 +1,6 @@
Name: docker-engine Name: docker-engine
Version: 18.09.0 Version: 18.09.0
Release: 100 Release: 101
Summary: The open-source application container engine Summary: The open-source application container engine
Group: Tools/Docker Group: Tools/Docker

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,204 @@
From 276da96d2e1019a36e4f7eeeb2f6cc9fd2963c97 Mon Sep 17 00:00:00 2001
From: lixiang <lixiang172@huawei.com>
Date: Thu, 19 Dec 2019 20:36:29 +0800
Subject: [PATCH] docker: clean code
reason: clean code
Change-Id: Iab01231af397f78813d4a8452b6021690997dd40
Signed-off-by: lixiang <lixiang172@huawei.com>
---
components/engine/api/server/router/container/inspect.go | 4 +++-
components/engine/cmd/dockerd/daemon.go | 8 +++++---
.../engine/cmd/dockerd/hack/malformed_host_override.go | 2 +-
components/engine/container/container.go | 2 +-
components/engine/daemon/graphdriver/overlay2/overlay.go | 9 +++++----
components/engine/image/tarexport/save.go | 3 ++-
components/engine/pkg/ioutils/fswriters.go | 16 +---------------
.../github.com/docker/libnetwork/osl/namespace_linux.go | 2 +-
.../engine/vendor/github.com/sirupsen/logrus/exported.go | 5 +++++
9 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/components/engine/api/server/router/container/inspect.go b/components/engine/api/server/router/container/inspect.go
index cb6eb50..7c9e5f2 100644
--- a/components/engine/api/server/router/container/inspect.go
+++ b/components/engine/api/server/router/container/inspect.go
@@ -5,6 +5,7 @@ import (
"net/http"
"strconv"
+ "github.com/sirupsen/logrus"
"github.com/docker/docker/api/server/httputils"
)
@@ -13,7 +14,8 @@ func (s *containerRouter) getContainersByName(ctx context.Context, w http.Respon
displaySize := httputils.BoolValue(r, "size")
version := httputils.VersionFromContext(ctx)
- timeout, _ := strconv.Atoi(r.Form.Get("t"))
+ timeout, sErr := strconv.Atoi(r.Form.Get("t"))
+ logrus.Devour(sErr)
json, err := s.backend.ContainerInspect(vars["name"], displaySize, version, timeout)
if err != nil {
return err
diff --git a/components/engine/cmd/dockerd/daemon.go b/components/engine/cmd/dockerd/daemon.go
index 336078f..0b3fa0e 100644
--- a/components/engine/cmd/dockerd/daemon.go
+++ b/components/engine/cmd/dockerd/daemon.go
@@ -93,9 +93,11 @@ func cleanupLocalDBs(run, root string) {
logrus.Errorf("stat dblock failed %v", err)
return
}
- ioutil.WriteFile(dbLockPath, []byte{}, 0600)
- files, _ := ioutil.ReadDir(filepath.Join(run, "containerd"))
- olds, _ := ioutil.ReadDir(filepath.Join(run, "libcontainerd"))
+ logrus.Devour(ioutil.WriteFile(dbLockPath, []byte{}, 0600))
+ files, err := ioutil.ReadDir(filepath.Join(run, "containerd"))
+ logrus.Devour(err)
+ olds, err := ioutil.ReadDir(filepath.Join(run, "libcontainerd"))
+ logrus.Devour(err)
files = append(files, olds...)
for _, f := range files {
if len(f.Name()) == 64 { // running container exist
diff --git a/components/engine/cmd/dockerd/hack/malformed_host_override.go b/components/engine/cmd/dockerd/hack/malformed_host_override.go
index 7852f62..6a8ab82 100644
--- a/components/engine/cmd/dockerd/hack/malformed_host_override.go
+++ b/components/engine/cmd/dockerd/hack/malformed_host_override.go
@@ -132,7 +132,7 @@ func (l *MalformedHostHeaderOverrideConn) Read(b []byte) (n int, err error) {
break
}
if i % 10 == 0 { // set interval = 1s
- l.Conn.SetReadDeadline(aLongTimeAgo)
+ logrus.Devour(l.Conn.SetReadDeadline(aLongTimeAgo))
logrus.Debugf("fix hijack by set read deadline force")
}
}
diff --git a/components/engine/container/container.go b/components/engine/container/container.go
index d9d97f4..53d41bd 100644
--- a/components/engine/container/container.go
+++ b/components/engine/container/container.go
@@ -783,7 +783,7 @@ func (c *Container) DropAccelAndCheckpointTo(store ViewDB) {
}
if shouldco {
- c.CheckpointTo(store)
+ logrus.Devour(c.CheckpointTo(store))
}
}
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
index 8f07d59..7fac2c3 100644
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
@@ -250,14 +250,16 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
}
func (d *Driver) cleanupLinkDir() {
- filepath.Walk(path.Join(d.home, linkDir), func(path string, f os.FileInfo, err error) error {
+ err := filepath.Walk(path.Join(d.home, linkDir), func(path string, f os.FileInfo, err error) error {
if _, serr := filepath.EvalSymlinks(path); serr != nil {
logrus.Warnf("[overlay2]: remove invalid symlink: %s", path)
- os.RemoveAll(path)
+ logrus.Devour(os.RemoveAll(path))
}
// always return nil, to walk all the symlink
return nil
})
+ logrus.Devour(err)
+
return
}
@@ -785,8 +787,7 @@ func (d *Driver) Exists(id string) bool {
// check symlink
_, rerr = os.Stat(path.Join(d.home, linkDir, string(lstr)))
if rerr != nil {
- os.RemoveAll(path.Join(d.home, linkDir, string(lstr)))
-
+ logrus.Devour(os.RemoveAll(path.Join(d.home, linkDir, string(lstr))))
logrus.Infof("[overlay2]: symlink (%s) is missing, create a new one", lstr)
if rerr = os.Symlink(path.Join("..", id, "diff"), path.Join(d.home, linkDir, string(lstr))); rerr != nil {
return false
diff --git a/components/engine/image/tarexport/save.go b/components/engine/image/tarexport/save.go
index 0683f17..f83a26e 100644
--- a/components/engine/image/tarexport/save.go
+++ b/components/engine/image/tarexport/save.go
@@ -21,6 +21,7 @@ import (
"github.com/docker/docker/pkg/system"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
type imageDescriptor struct {
@@ -415,7 +416,7 @@ func (s *saveSession) saveLayer(id layer.ChainID, legacyImg image.V1Image, creat
if s.compress {
reader, compressionDone = dd.Compress(arch)
defer func(closer io.Closer) {
- closer.Close()
+ logrus.Devour(closer.Close())
<-compressionDone
}(reader)
}
diff --git a/components/engine/pkg/ioutils/fswriters.go b/components/engine/pkg/ioutils/fswriters.go
index 093f11a..5d68dee 100644
--- a/components/engine/pkg/ioutils/fswriters.go
+++ b/components/engine/pkg/ioutils/fswriters.go
@@ -30,20 +30,6 @@ func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, err
}, nil
}
-func CleanupTmpFilesRecursive(rootDir string) {
- var removals []string
- filepath.Walk(rootDir, func(path string, f os.FileInfo, err error) error {
- if strings.HasPrefix(f.Name(), ".tmp-") {
- removals = append(removals, path)
- }
- return nil
- })
-
- for _, r := range removals {
- os.RemoveAll(r)
- }
-}
-
// CleanupAtomicFile cleanup redundant atomic files
func CleanupAtomicFile(filename string) error {
baseName := ".tmp-" + filepath.Base(filename)
@@ -57,7 +43,7 @@ func CleanupAtomicFile(filename string) error {
for _, f := range fs {
if strings.Contains(f.Name(), baseName) {
logrus.Warnf("Remove temporary file: %s", filepath.Join(dir, f.Name()))
- os.RemoveAll(filepath.Join(dir, f.Name()))
+ logrus.Devour(os.RemoveAll(filepath.Join(dir, f.Name())))
}
}
return nil
diff --git a/components/engine/vendor/github.com/docker/libnetwork/osl/namespace_linux.go b/components/engine/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
index f97b286..03537bd 100644
--- a/components/engine/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
+++ b/components/engine/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
@@ -611,7 +611,7 @@ func NetnsFileCleanup(activeSandboxes map[string]interface{}) {
if _, ok := activeSandboxesMap[id]; !ok {
path := filepath.Join(prefix, id)
// cleanup netns file if not active
- syscall.Unmount(path, syscall.MNT_DETACH)
+ logrus.Devour(syscall.Unmount(path, syscall.MNT_DETACH))
if err := os.Remove(path); err != nil {
logrus.Warnf("Failed to cleanup netns file %s: %s", path, err)
}
diff --git a/components/engine/vendor/github.com/sirupsen/logrus/exported.go b/components/engine/vendor/github.com/sirupsen/logrus/exported.go
index eb612a6..db23fd5 100644
--- a/components/engine/vendor/github.com/sirupsen/logrus/exported.go
+++ b/components/engine/vendor/github.com/sirupsen/logrus/exported.go
@@ -199,3 +199,7 @@ func Panicln(args ...interface{}) {
func Fatalln(args ...interface{}) {
std.Fatalln(args...)
}
+
+// Devour will eats any error
+func Devour(err error) {
+}
--
1.8.3.1

View File

@ -0,0 +1,71 @@
From 39da5897107b49f25f9c318a04ad79ec6753fb7a Mon Sep 17 00:00:00 2001
From: jingrui <jingrui@huawei.com>
Date: Tue, 31 Dec 2019 11:11:25 +0800
Subject: [PATCH] docker: fix merge accel env rewriten
Change-Id: If2c4c076d56e7807d0dceae9db63e7fe1a0492ba
Signed-off-by: jingrui <jingrui@huawei.com>
---
components/engine/container/container.go | 39 +++++++++++++++++++++---
1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/components/engine/container/container.go b/components/engine/container/container.go
index d9d97f4022..8fd275ffa9 100644
--- a/components/engine/container/container.go
+++ b/components/engine/container/container.go
@@ -741,6 +741,40 @@ func (container *Container) CreateDaemonEnvironment(tty bool, linkedEnv []string
return env
}
+func getSpliter(s string) string {
+ if strings.Contains(s, ",") {
+ return ","
+ }
+ if strings.Contains(s, ";") {
+ return ";"
+ }
+ return ":"
+}
+
+func mergeOneEnv(el []string, k, v string) []string {
+ for i, e := range el {
+ ee := strings.SplitN(e, "=", 2)
+ if ee[0] != k {
+ continue
+ }
+ if len(ee) > 1 {
+ sep := getSpliter(ee[1] + v)
+ el[i] = k + "=" + ee[1] + sep + v
+ } else {
+ el[i] = k + "=" + v
+ }
+ return el
+ }
+ return append(el, k+"="+v)
+}
+
+func mergeEnv(el []string, em map[string]string) []string {
+ for k, v := range em {
+ el = mergeOneEnv(el, k, v)
+ }
+ return el
+}
+
func (c *Container) DropAccelAndCheckpointTo(store ViewDB) {
hc := c.HostConfig
cc := c.Config
@@ -773,10 +807,7 @@ func (c *Container) DropAccelAndCheckpointTo(store ViewDB) {
}
if len(hc.AccelEnvironments) != 0 {
- for k, v := range hc.AccelEnvironments {
- env := fmt.Sprintf("%s=%s", k, v)
- cc.Env = append(cc.Env, env)
- }
+ cc.Env = mergeEnv(cc.Env, hc.AccelEnvironments)
logrus.Infof("upgrade Env %s", cc.Env)
hc.AccelEnvironments = nil
shouldco = true
--
2.17.1

View File

@ -0,0 +1,32 @@
From d66f2fd39cd2a86ab96e762a79659e677f0af6e4 Mon Sep 17 00:00:00 2001
From: xiadanni1 <xiadanni1@huawei.com>
Date: Wed, 8 Jan 2020 20:49:55 +0800
Subject: [PATCH] docker: update log-opt when upgrade from 1.11.2
reason:Container's default log tag begins with "docker" in 1.11.2,
but not in 18.09, which is not good for log filtering. So we modify
this to allow users to update containers' log tags by setting deamon
config.
Change-Id: I9b30e8fe314a272ed187911d843d803277128b76
Signed-off-by: xiadanni1 <xiadanni1@huawei.com>
---
components/engine/daemon/daemon.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
index 3bd0d93..0dab6db 100644
--- a/components/engine/daemon/daemon.go
+++ b/components/engine/daemon/daemon.go
@@ -327,7 +327,7 @@ func (daemon *Daemon) restore() error {
// The LogConfig.Type is empty if the container was created before docker 1.12 with default log driver.
// We should rewrite it to use the daemon defaults.
// Fixes https://github.com/docker/docker/issues/22536
- if c.HostConfig.LogConfig.Type == "" {
+ if c.HostConfig.LogConfig.Type == "" || c.HostConfig.LogConfig.Type == daemon.defaultLogConfig.Type {
if err := daemon.mergeAndVerifyLogConfig(&c.HostConfig.LogConfig); err != nil {
logrus.Errorf("Failed to verify log config for container %s: %q", c.ID, err)
continue
--
1.8.3.1

View File

@ -0,0 +1,65 @@
From b254e628f9745f4b7b2b56f6b2818c6c6ad76d31 Mon Sep 17 00:00:00 2001
From: xiadanni1 <xiadanni1@huawei.com>
Date: Thu, 9 Jan 2020 03:06:30 +0800
Subject: [PATCH] docekr: only update log-opt tag for containers from 1.11.2
reason:only update log-opt tag for containers from 1.11.2
to minimize influence on configs.
Change-Id: I6eea45477a75063c7b5c296755d28f70dc200117
Signed-off-by: xiadanni1 <xiadanni1@huawei.com>
---
components/engine/daemon/daemon.go | 7 ++++++-
components/engine/daemon/logs.go | 14 ++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
index 0dab6db..f591878 100644
--- a/components/engine/daemon/daemon.go
+++ b/components/engine/daemon/daemon.go
@@ -327,11 +327,16 @@ func (daemon *Daemon) restore() error {
// The LogConfig.Type is empty if the container was created before docker 1.12 with default log driver.
// We should rewrite it to use the daemon defaults.
// Fixes https://github.com/docker/docker/issues/22536
- if c.HostConfig.LogConfig.Type == "" || c.HostConfig.LogConfig.Type == daemon.defaultLogConfig.Type {
+ if c.HostConfig.LogConfig.Type == "" {
if err := daemon.mergeAndVerifyLogConfig(&c.HostConfig.LogConfig); err != nil {
logrus.Errorf("Failed to verify log config for container %s: %q", c.ID, err)
continue
}
+ } else if c.HostConfig.LogConfig.Type == daemon.defaultLogConfig.Type {
+ if err := daemon.mergeAndVerifyOriginContainersLogConfig(&c.HostConfig.LogConfig); err != nil {
+ logrus.Errorf("Failed to verify log config for container %s: %q", c.ID, err)
+ continue
+ }
}
}
diff --git a/components/engine/daemon/logs.go b/components/engine/daemon/logs.go
index 668a75c..8dddbcf 100644
--- a/components/engine/daemon/logs.go
+++ b/components/engine/daemon/logs.go
@@ -193,6 +193,20 @@ func (daemon *Daemon) mergeAndVerifyLogConfig(cfg *containertypes.LogConfig) err
return logger.ValidateLogOpts(cfg.Type, cfg.Config)
}
+func (daemon *Daemon) mergeAndVerifyOriginContainersLogConfig(cfg *containertypes.LogConfig) error {
+ if cfg.Config == nil {
+ cfg.Config = make(map[string]string)
+ }
+
+ if _, ok := daemon.defaultLogConfig.Config["tag"]; ok {
+ if _, ok := cfg.Config["tag"]; !ok {
+ cfg.Config["tag"] = daemon.defaultLogConfig.Config["tag"]
+ }
+ }
+
+ return logger.ValidateLogOpts(cfg.Type, cfg.Config)
+}
+
func (daemon *Daemon) setupDefaultLogConfig() error {
config := daemon.configStore
if len(config.LogConfig.Config) > 0 {
--
1.8.3.1

View File

@ -0,0 +1,52 @@
From b8160cf70bcb59ff4baea98f8e6eeb700b69eea1 Mon Sep 17 00:00:00 2001
From: lixiang <lixiang172@huawei.com>
Date: Sun, 19 Jan 2020 09:09:14 +0800
Subject: [PATCH] docker: Support check manifest and layer's DiffID info when
pulling image failed
reason: When pulling image, the downloaded layer and the layer recorded in
the config could be different and which will cause the
"errRootFSMismatch" error. What we should do is to trace more info on that and
log them for better analysing after error occured.
Change-Id: Ib09a840e34becd403f0336ae8c93c0f4aa064095
Signed-off-by: lixiang <lixiang172@huawei.com>
---
components/engine/distribution/pull_v2.go | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/components/engine/distribution/pull_v2.go b/components/engine/distribution/pull_v2.go
index 9d2a303..99cee79 100644
--- a/components/engine/distribution/pull_v2.go
+++ b/components/engine/distribution/pull_v2.go
@@ -399,11 +399,13 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named, platform
case *schema2.DeserializedManifest:
id, manifestDigest, err = p.pullSchema2(ctx, ref, v, platform)
if err != nil {
+ logrus.Errorf("try to pull schema2 failed. manifest: %+v", manifest.References())
return false, err
}
case *manifestlist.DeserializedManifestList:
id, manifestDigest, err = p.pullManifestList(ctx, ref, v, platform)
if err != nil {
+ logrus.Errorf("try to get manifest data from storage failed. manifest: %+v", manifest.References())
return false, err
}
default:
@@ -714,11 +716,13 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
// Otherwise the image config could be referencing layers that aren't
// included in the manifest.
if len(downloadedRootFS.DiffIDs) != len(configRootFS.DiffIDs) {
+ logrus.Errorf("config layers: %v pulled/loaded: %v", configRootFS.DiffIDs, downloadedRootFS.DiffIDs)
return "", "", errRootFSMismatch
}
for i := range downloadedRootFS.DiffIDs {
if downloadedRootFS.DiffIDs[i] != configRootFS.DiffIDs[i] {
+ logrus.Errorf("config layer do not match pulled/loaded layer. config:%v pulled:%v", configRootFS.DiffIDs[i], downloadedRootFS.DiffIDs[i])
return "", "", errRootFSMismatch
}
}
--
1.8.3.1

View File

@ -0,0 +1,904 @@
From ca795c91b91ea38ce26616825c646f59a746edde Mon Sep 17 00:00:00 2001
From: jiangpengfei <jiangpengfei9@huawei.com>
Date: Mon, 30 Sep 2019 14:15:45 -0400
Subject: [PATCH] docker: support private registry
reason:
1. add registries config to support downnload private registry image
2. add LLT testcases for registries config
Change-Id: Icd77363c6c2024e9ece0b79e65aeaee3af928caa
Signed-off-by: jiangpengfei <jiangpengfei9@huawei.com>
---
components/engine/api/types/registry/registry.go | 162 ++++++++++++++++++++-
.../engine/api/types/registry/registry_test.go | 73 ++++++++++
components/engine/cmd/dockerd/daemon_test.go | 24 +++
components/engine/daemon/config/config.go | 13 ++
components/engine/daemon/reload.go | 26 ++++
components/engine/distribution/pull_v2.go | 26 +++-
components/engine/distribution/push_v2_test.go | 4 +
components/engine/opts/opts.go | 34 +++++
components/engine/registry/config.go | 24 ++-
components/engine/registry/service.go | 12 ++
components/engine/registry/service_v2.go | 98 +++++++++----
components/engine/registry/service_v2_test.go | 104 +++++++++++++
12 files changed, 564 insertions(+), 36 deletions(-)
create mode 100644 components/engine/api/types/registry/registry_test.go
create mode 100644 components/engine/registry/service_v2_test.go
diff --git a/components/engine/api/types/registry/registry.go b/components/engine/api/types/registry/registry.go
index 8789ad3..1ebf18b 100644
--- a/components/engine/api/types/registry/registry.go
+++ b/components/engine/api/types/registry/registry.go
@@ -2,9 +2,25 @@ package registry // import "github.com/docker/docker/api/types/registry"
import (
"encoding/json"
+ "fmt"
"net"
+ "net/url"
+ "regexp"
+ "strings"
- "github.com/opencontainers/image-spec/specs-go/v1"
+ "github.com/docker/distribution/reference"
+ v1 "github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+var (
+ // DefaultEndpoint for docker.io
+ DefaultEndpoint = Endpoint{
+ Address: "https://registry-1.docker.io",
+ url: url.URL{
+ Scheme: "https",
+ Host: "registry-1.docker.io",
+ },
+ }
)
// ServiceConfig stores daemon registry services configuration.
@@ -14,6 +30,150 @@ type ServiceConfig struct {
InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"`
IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"`
Mirrors []string
+ Registries Registries
+}
+
+// Registries is a slice of type Registry.
+type Registries []Registry
+
+// Registry includes all data relevant for the lookup of push and pull
+// endpoints.
+type Registry struct {
+ // Pattern is a string contains the registry domain name which pull/push
+ // images directly, don't need to convert to pull from mirror registry
+ Pattern string `json:"pattern"`
+ // Mirrors is a slice contains registry mirror url address
+ Mirrors []Endpoint `json:"mirrors"`
+ patternRegexp *regexp.Regexp
+}
+
+// Endpoint includes all data associated with a given registry endpoint.
+type Endpoint struct {
+ // Address is the endpoints base URL when assembling a repository in a
+ // registry (e.g., "registry.com:5000/v2").
+ Address string `json:"address"`
+ // url is used during endpoint lookup and avoids to redundantly parse
+ // Address when the Endpoint is used.
+ url url.URL
+ // InsecureSkipVerify: if true, TLS accepts any certificate presented
+ // by the server and any host name in that certificate. In this mode,
+ // TLS is susceptible to man-in-the-middle attacks. This should be used
+ // only for testing
+ InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
+}
+
+// RewriteReference strips the prefix from ref and appends it to registry.
+// If the prefix is empty, ref remains unchanged. An error is returned if
+// prefix doesn't prefix ref.
+func RewriteReference(ref reference.Named, prefix string, registry *url.URL) (reference.Named, error) {
+ // Sanity check the provided arguments
+ if ref == nil {
+ return nil, fmt.Errorf("provided reference is nil")
+ }
+ if registry == nil {
+ return nil, fmt.Errorf("provided registry is nil")
+ }
+
+ // don't rewrite the default endpoints
+ if *registry == DefaultEndpoint.url {
+ return ref, nil
+ }
+
+ if prefix == "" {
+ return ref, nil
+ }
+
+ baseAddress := strings.TrimPrefix(registry.String(), registry.Scheme+"://")
+
+ refStr := ref.String()
+ if !strings.HasPrefix(refStr, prefix) {
+ return nil, fmt.Errorf("unable to rewrite reference %q with prefix %q", refStr, prefix)
+ }
+ remainder := strings.TrimPrefix(refStr, prefix)
+ remainder = strings.TrimPrefix(remainder, "/")
+ baseAddress = strings.TrimSuffix(baseAddress, "/")
+
+ newRefStr := baseAddress + "/" + remainder
+ newRef, err := reference.ParseNamed(newRefStr)
+ if err != nil {
+ return nil, fmt.Errorf("unable to rewrite reference %q with prefix %q to %q: %v", refStr, prefix, newRefStr, err)
+ }
+ return newRef, nil
+}
+
+// GetURL returns the Endpoint's URL.
+func (r *Endpoint) GetURL() *url.URL {
+ // return the pointer of a copy
+ url := r.url
+ return &url
+}
+
+// MatchWhiteList return reference match the r.whiteListRegexp or not
+func (r *Registry) MatchPattern(reference string) bool {
+ if r.patternRegexp == nil {
+ return false
+ }
+
+ return r.patternRegexp.MatchString(reference)
+}
+
+// FindRegistry returns the Registry mirror url address if reference not in the whitelist
+// or nil if reference in the Registry whitelist.
+func (r Registries) FindRegistry(reference string) *Registry {
+ var reg *Registry = nil
+ for i := range r {
+ match := r[i].MatchPattern(reference)
+ if match {
+ reg = &r[i]
+ break
+ }
+ }
+
+ return reg
+}
+
+// Prepare must be called on each new Registry. It sets up all specified push
+// and pull endpoints
+func (r *Registry) Prepare() error {
+ var err error
+ r.patternRegexp, err = regexp.Compile(r.Pattern)
+ if err != nil {
+ return fmt.Errorf("invalid pattern: %v", err)
+ }
+
+ prepareEndpoints := func(endpoints []Endpoint) ([]Endpoint, error) {
+ for i := range endpoints {
+ if err := endpoints[i].Prepare(); err != nil {
+ return nil, err
+ }
+ }
+
+ return endpoints, nil
+ }
+
+ if r.Mirrors, err = prepareEndpoints(r.Mirrors); err != nil {
+ return err
+ }
+
+ if len(r.Mirrors) == 0 {
+ return fmt.Errorf("Registry with whitelist %v without mirror endpoints", r.Pattern)
+ }
+
+ return nil
+}
+
+// Prepare sets up the Endpoint.
+func (r *Endpoint) Prepare() error {
+ if !strings.HasPrefix(r.Address, "http://") && !strings.HasPrefix(r.Address, "https://") {
+ return fmt.Errorf("%s: address must start with %q or %q", r.Address, "http://", "https://")
+ }
+
+ u, err := url.Parse(r.Address)
+ if err != nil {
+ return err
+ }
+ r.url = *u
+ return nil
}
// NetIPNet is the net.IPNet type, which can be marshalled and
diff --git a/components/engine/api/types/registry/registry_test.go b/components/engine/api/types/registry/registry_test.go
new file mode 100644
index 0000000..e532d4d
--- /dev/null
+++ b/components/engine/api/types/registry/registry_test.go
@@ -0,0 +1,73 @@
+package registry
+
+import (
+ "net/url"
+ "testing"
+
+ "github.com/docker/distribution/reference"
+ "gotest.tools/assert"
+)
+
+func TestRewriteReference(t *testing.T) {
+ var ref reference.Named
+ var prefix string
+ var registry *url.URL
+
+ // case 1: ref is nil
+ _, err := RewriteReference(ref, prefix, registry)
+ assert.ErrorContains(t, err, "provided reference is nil")
+
+ ref, err = reference.ParseNormalizedNamed("hello.com/official/busybox")
+ assert.NilError(t, err)
+
+ // case 2: registry is nil
+ _, err = RewriteReference(ref, prefix, registry)
+ assert.ErrorContains(t, err, "provided registry is nil")
+
+ registry = &url.URL{
+ Scheme: "https",
+ Host: "exapmle.com",
+ }
+
+ // case 3: prefix is empty, expect nil
+ rewriteRef, err := RewriteReference(ref, prefix, registry)
+ assert.NilError(t, err)
+ assert.Equal(t, rewriteRef, ref)
+
+ // case 4: registry equal to DefaultEndpoint.url
+ registry = &url.URL{
+ Scheme: "https",
+ Host: "registry-1.docker.io",
+ }
+ rewriteRef, err = RewriteReference(ref, prefix, registry)
+ assert.NilError(t, err)
+ assert.Equal(t, rewriteRef, ref)
+
+ // case 5: ref.String() doesn't have prefix
+ registry = &url.URL{
+ Scheme: "https",
+ Host: "test.io",
+ }
+ prefix = "example.com"
+ rewriteRef, err = RewriteReference(ref, prefix, registry)
+ assert.ErrorContains(t, err, "unable to rewrite reference")
+
+ // case 6: registry host is invalid
+ prefix = "hello.com"
+ registry = &url.URL{
+ Scheme: "https",
+ Host: "[?f,*fds",
+ }
+ rewriteRef, err = RewriteReference(ref, prefix, registry)
+ assert.ErrorContains(t, err, "unable to rewrite reference")
+
+ // case 7: everything is ok
+ registry = &url.URL{
+ Scheme: "https",
+ Host: "test.io",
+ }
+ prefix = "hello.com"
+ rewriteRef, err = RewriteReference(ref, prefix, registry)
+ assert.NilError(t, err)
+ assert.Equal(t, rewriteRef.String(), "test.io/official/busybox")
+}
diff --git a/components/engine/cmd/dockerd/daemon_test.go b/components/engine/cmd/dockerd/daemon_test.go
index ad447e3..681bf87 100644
--- a/components/engine/cmd/dockerd/daemon_test.go
+++ b/components/engine/cmd/dockerd/daemon_test.go
@@ -180,3 +180,27 @@ func TestLoadDaemonConfigWithRegistryOptions(t *testing.T) {
assert.Check(t, is.Len(loadedConfig.Mirrors, 1))
assert.Check(t, is.Len(loadedConfig.InsecureRegistries, 1))
}
+
+func TestLoadDaemonConfigWithRegistriesOptions(t *testing.T) {
+ content := `{
+ "registries": [
+ {
+ "pattern": "xxx.com",
+ "mirrors": [
+ {
+ "address": "http://hello.mirror.com"
+ }
+ ]
+ }
+ ]
+ }`
+ tempFile := fs.NewFile(t, "config", fs.WithContent(content))
+ defer tempFile.Remove()
+
+ opts := defaultOptions(tempFile.Path())
+ loadedConfig, err := loadDaemonCliConfig(opts)
+ assert.NilError(t, err)
+ assert.Assert(t, loadedConfig != nil)
+
+ assert.Check(t, is.Len(loadedConfig.Registries, 1))
+}
diff --git a/components/engine/daemon/config/config.go b/components/engine/daemon/config/config.go
index 2141ce8..07d4c89 100644
--- a/components/engine/daemon/config/config.go
+++ b/components/engine/daemon/config/config.go
@@ -435,6 +435,10 @@ func getConflictFreeConfiguration(configFile string, flags *pflag.FlagSet) (*Con
return nil, err
}
+ if len(config.Mirrors) > 0 && len(config.Registries) > 0 {
+ return nil, fmt.Errorf("registry-mirror config conflict with registries config")
+ }
+
if config.RootDeprecated != "" {
logrus.Warn(`The "graph" config file option is deprecated. Please use "data-root" instead.`)
@@ -472,6 +476,10 @@ func findConfigurationConflicts(config map[string]interface{}, flags *pflag.Flag
unknownKeys := make(map[string]interface{})
for key, value := range config {
if flag := flags.Lookup(key); flag == nil && !skipValidateOptions[key] {
+ // skip config-only flags
+ if key == "registries" {
+ continue
+ }
unknownKeys[key] = value
}
}
@@ -579,6 +587,11 @@ func Validate(config *Config) error {
}
}
+ // validate registries mirror settings
+ if err := opts.ValidateRegistries(config.Registries); err != nil {
+ return err
+ }
+
// validate platform-specific settings
return config.ValidatePlatformConfig()
}
diff --git a/components/engine/daemon/reload.go b/components/engine/daemon/reload.go
index 026d7dd..b8132cc 100644
--- a/components/engine/daemon/reload.go
+++ b/components/engine/daemon/reload.go
@@ -65,6 +65,9 @@ func (daemon *Daemon) Reload(conf *config.Config) (err error) {
if err := daemon.reloadLiveRestore(conf, attributes); err != nil {
return err
}
+ if err := daemon.reloadRegistries(conf, attributes);err != nil {
+ return err
+ }
return daemon.reloadNetworkDiagnosticPort(conf, attributes)
}
@@ -294,6 +297,29 @@ func (daemon *Daemon) reloadRegistryMirrors(conf *config.Config, attributes map[
return nil
}
+// reloadRegistries updates the registries configuration and the passed attributes
+func (daemon *Daemon) reloadRegistries(conf *config.Config, attributes map[string]string) error {
+ // update corresponding configuration
+ if conf.IsValueSet("registries") {
+ daemon.configStore.Registries = conf.Registries
+ if err := daemon.RegistryService.LoadRegistries(conf.Registries); err != nil {
+ return err
+ }
+ }
+
+ // prepare reload event attributes with updatable configurations
+ if daemon.configStore.Registries != nil {
+ registries, err := json.Marshal(daemon.configStore.Registries)
+ if err != nil {
+ return err
+ }
+ attributes["registries"] = string(registries)
+ } else {
+ attributes["registries"] = "[]"
+ }
+ return nil
+}
+
// reloadLiveRestore updates configuration with live retore option
// and updates the passed attributes
func (daemon *Daemon) reloadLiveRestore(conf *config.Config, attributes map[string]string) error {
diff --git a/components/engine/distribution/pull_v2.go b/components/engine/distribution/pull_v2.go
index 99cee79..4150241 100644
--- a/components/engine/distribution/pull_v2.go
+++ b/components/engine/distribution/pull_v2.go
@@ -20,10 +20,11 @@ import (
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/distribution/registry/client/auth"
"github.com/docker/distribution/registry/client/transport"
+ registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/distribution/metadata"
"github.com/docker/docker/distribution/xfer"
"github.com/docker/docker/image"
- "github.com/docker/docker/image/v1"
+ v1 "github.com/docker/docker/image/v1"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/progress"
@@ -66,6 +67,10 @@ type v2Puller struct {
func (p *v2Puller) Pull(ctx context.Context, ref reference.Named, platform *specs.Platform) (err error) {
// TODO(tiborvass): was ReceiveTimeout
+ if p.endpoint.Prefix != "" {
+ p.config.MetaHeaders["Docker-Prefix"] = []string{p.endpoint.Prefix}
+ }
+
p.repo, p.confirmedV2, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "pull")
if err != nil {
logrus.Warnf("Error getting v2 registry: %v", err)
@@ -334,6 +339,17 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named, platform
return false, err
}
+ var pullRef reference.Named = ref
+ if len(p.endpoint.Prefix) != 0 {
+ // Note that pullRef is only used for pulling while ref is used as
+ // the reference for storing the image
+ pullRef, err = registrytypes.RewriteReference(ref, p.endpoint.Prefix, p.endpoint.URL)
+ if err != nil {
+ return false, err
+ }
+ logrus.Infof("rewriting %q to %q", ref.String(), pullRef.String())
+ }
+
var (
manifest distribution.Manifest
tagOrDigest string // Used for logging/progress only
@@ -379,7 +395,7 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named, platform
// the other side speaks the v2 protocol.
p.confirmedV2 = true
- logrus.Debugf("Pulling ref from V2 registry: %s", reference.FamiliarString(ref))
+ logrus.Debugf("Pulling ref %q from V2 registry: %s", ref, p.endpoint.URL)
progress.Message(p.config.ProgressOutput, tagOrDigest, "Pulling from "+reference.FamiliarName(p.repo.Named()))
var (
@@ -392,18 +408,18 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named, platform
if p.config.RequireSchema2 {
return false, fmt.Errorf("invalid manifest: not schema2")
}
- id, manifestDigest, err = p.pullSchema1(ctx, ref, v, platform)
+ id, manifestDigest, err = p.pullSchema1(ctx, pullRef, v, platform)
if err != nil {
return false, err
}
case *schema2.DeserializedManifest:
- id, manifestDigest, err = p.pullSchema2(ctx, ref, v, platform)
+ id, manifestDigest, err = p.pullSchema2(ctx, pullRef, v, platform)
if err != nil {
logrus.Errorf("try to pull schema2 failed. manifest: %+v", manifest.References())
return false, err
}
case *manifestlist.DeserializedManifestList:
- id, manifestDigest, err = p.pullManifestList(ctx, ref, v, platform)
+ id, manifestDigest, err = p.pullManifestList(ctx, pullRef, v, platform)
if err != nil {
logrus.Errorf("try to get manifest data from storage failed. manifest: %+v", manifest.References())
return false, err
diff --git a/components/engine/distribution/push_v2_test.go b/components/engine/distribution/push_v2_test.go
index 436b4a1..8d39403 100644
--- a/components/engine/distribution/push_v2_test.go
+++ b/components/engine/distribution/push_v2_test.go
@@ -488,6 +488,10 @@ func (s *mockReferenceStore) Get(ref reference.Named) (digest.Digest, error) {
return "", nil
}
+func (s *mockReferenceStore) List() []digest.Digest {
+ return []digest.Digest{}
+}
+
func TestWhenEmptyAuthConfig(t *testing.T) {
for _, authInfo := range []struct {
username string
diff --git a/components/engine/opts/opts.go b/components/engine/opts/opts.go
index de8aacb..db63aa6 100644
--- a/components/engine/opts/opts.go
+++ b/components/engine/opts/opts.go
@@ -7,6 +7,7 @@ import (
"regexp"
"strings"
+ "github.com/docker/docker/api/types/registry"
"github.com/docker/go-units"
)
@@ -15,6 +16,11 @@ var (
domainRegexp = regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`)
)
+const (
+ maxRegistryNum = 100
+ maxMirrorNumber = 100
+)
+
// ListOpts holds a list of values and a validation function.
type ListOpts struct {
values *[]string
@@ -273,6 +279,34 @@ func ValidateSingleGenericResource(val string) (string, error) {
return val, nil
}
+func ValidateRegistries(registries registry.Registries) error {
+ if len(registries) == 0 {
+ return nil
+ }
+
+ if len(registries) > maxRegistryNum {
+ return fmt.Errorf("registries config registry number should not larger than %d", maxRegistryNum)
+ }
+
+ for _, reg := range registries {
+ if len(reg.Pattern) == 0 || len(reg.Mirrors) == 0 {
+ return fmt.Errorf("registry pattern and mirrors is required, should not be empty")
+ }
+
+ if len(reg.Mirrors) > maxMirrorNumber {
+ return fmt.Errorf("registry mirrors number should not larger than %d", maxMirrorNumber)
+ }
+
+ for _, mirror := range reg.Mirrors {
+ if len(mirror.Address) == 0 {
+ return fmt.Errorf("mirror address is required, should not be empty")
+ }
+ }
+ }
+
+ return nil
+}
+
// ParseLink parses and validates the specified string as a link format (name:alias)
func ParseLink(val string) (string, string, error) {
if val == "" {
diff --git a/components/engine/registry/config.go b/components/engine/registry/config.go
index ea491b9..9c2b762 100644
--- a/components/engine/registry/config.go
+++ b/components/engine/registry/config.go
@@ -20,6 +20,10 @@ type ServiceOptions struct {
Mirrors []string `json:"registry-mirrors,omitempty"`
InsecureRegistries []string `json:"insecure-registries,omitempty"`
+ // Registries holds information associated with registries and their
+ // push and pull mirrors.
+ Registries registrytypes.Registries `json:"registries,omitempty"`
+
// 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"`
@@ -97,6 +101,9 @@ func newServiceConfig(options ServiceOptions) (*serviceConfig, error) {
if err := config.LoadInsecureRegistries(options.InsecureRegistries); err != nil {
return nil, err
}
+ if err := config.LoadRegistries(options.Registries); err != nil {
+ return nil, err
+ }
return config, nil
}
@@ -248,7 +255,22 @@ skip:
return nil
}
-// allowNondistributableArtifacts returns true if the provided hostname is part of the list of registries
+// LoadRegistries loads the user-specified configuration options for registries
+func (config *serviceConfig) LoadRegistries(registries registrytypes.Registries) error {
+ for _, registry := range registries {
+ if err := registry.Prepare(); err != nil {
+ return err
+ }
+ config.Registries = append(config.Registries, registry)
+ }
+
+ for i, r := range config.Registries {
+ logrus.Infof("REGISTRY %d: %v", i, r)
+ }
+ return nil
+}
+
+// allowNondistributableArtifacts returns true if the provided hostname is part of the list of regsitries
// that allow push of nondistributable artifacts.
//
// The list can contain elements with CIDR notation to specify a whole subnet. If the subnet contains an IP
diff --git a/components/engine/registry/service.go b/components/engine/registry/service.go
index d38f44b..8530f97 100644
--- a/components/engine/registry/service.go
+++ b/components/engine/registry/service.go
@@ -34,6 +34,7 @@ type Service interface {
LoadAllowNondistributableArtifacts([]string) error
LoadMirrors([]string) error
LoadInsecureRegistries([]string) error
+ LoadRegistries(registrytypes.Registries) error
}
// DefaultService is a registry service. It tracks configuration data such as a list
@@ -64,6 +65,7 @@ func (s *DefaultService) ServiceConfig() *registrytypes.ServiceConfig {
InsecureRegistryCIDRs: make([]*(registrytypes.NetIPNet), 0),
IndexConfigs: make(map[string]*(registrytypes.IndexInfo)),
Mirrors: make([]string, 0),
+ Registries: make([]registrytypes.Registry, 0),
}
// construct a new ServiceConfig which will not retrieve s.Config directly,
@@ -77,6 +79,7 @@ func (s *DefaultService) ServiceConfig() *registrytypes.ServiceConfig {
}
servConfig.Mirrors = append(servConfig.Mirrors, s.config.ServiceConfig.Mirrors...)
+ servConfig.Registries = append(servConfig.Registries, s.config.ServiceConfig.Registries...)
return &servConfig
}
@@ -105,6 +108,14 @@ func (s *DefaultService) LoadInsecureRegistries(registries []string) error {
return s.config.LoadInsecureRegistries(registries)
}
+// LoadRegistries loads registries for Service
+func (s *DefaultService) LoadRegistries(registries registrytypes.Registries) error {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ return s.config.LoadRegistries(registries)
+}
+
// Auth contacts the public registry with the provided credentials,
// and returns OK if authentication was successful.
// It can be used to verify the validity of a client's credentials.
@@ -258,6 +269,7 @@ type APIEndpoint struct {
Official bool
TrimHostname bool
TLSConfig *tls.Config
+ Prefix string
}
// ToV1Endpoint returns a V1 API endpoint based on the APIEndpoint
diff --git a/components/engine/registry/service_v2.go b/components/engine/registry/service_v2.go
index 3a56dc9..adeb10c 100644
--- a/components/engine/registry/service_v2.go
+++ b/components/engine/registry/service_v2.go
@@ -1,47 +1,87 @@
package registry // import "github.com/docker/docker/registry"
import (
+ "crypto/tls"
"net/url"
"strings"
+ registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/go-connections/tlsconfig"
)
func (s *DefaultService) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, err error) {
- tlsConfig := tlsconfig.ServerDefault()
- if hostname == DefaultNamespace || hostname == IndexHostname {
- // 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
+ var tlsConfig *tls.Config
+
+ // if s.config.Registries is set, lookup regsitry mirror addr from s.config.Registries
+ if len(s.config.Registries) > 0 {
+ reg := s.config.Registries.FindRegistry(hostname)
+
+ if reg != nil {
+ var regEndpoints []registrytypes.Endpoint = reg.Mirrors
+
+ lastIndex := len(regEndpoints) - 1
+ for i, regEP := range regEndpoints {
+ official := regEP.Address == registrytypes.DefaultEndpoint.Address
+ regURL := regEP.GetURL()
+
+ if official {
+ tlsConfig = tlsconfig.ServerDefault()
+ } else {
+ tlsConfig, err = s.tlsConfigForMirror(regURL)
+ if err != nil {
+ return nil, err
+ }
+ }
+ tlsConfig.InsecureSkipVerify = regEP.InsecureSkipVerify
+ endpoints = append(endpoints, APIEndpoint{
+ URL: regURL,
+ Version: APIVersion2,
+ Official: official,
+ TrimHostname: true,
+ TLSConfig: tlsConfig,
+ Prefix: hostname,
+ // the last endpoint is not considered a mirror
+ Mirror: i != lastIndex,
+ })
}
- mirrorTLSConfig, err := s.tlsConfigForMirror(mirrorURL)
- if err != nil {
- return nil, err
+ return endpoints, nil
+ }
+ } else {
+ tlsConfig = tlsconfig.ServerDefault()
+ if hostname == DefaultNamespace || hostname == IndexHostname {
+ // 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
+ }
+ mirrorTLSConfig, err := s.tlsConfigForMirror(mirrorURL)
+ if err != nil {
+ return nil, err
+ }
+ endpoints = append(endpoints, APIEndpoint{
+ URL: mirrorURL,
+ // guess mirrors are v2
+ Version: APIVersion2,
+ Mirror: true,
+ TrimHostname: true,
+ TLSConfig: mirrorTLSConfig,
+ })
}
+ // v2 registry
endpoints = append(endpoints, APIEndpoint{
- URL: mirrorURL,
- // guess mirrors are v2
+ URL: DefaultV2Registry,
Version: APIVersion2,
- Mirror: true,
+ Official: true,
TrimHostname: true,
- TLSConfig: mirrorTLSConfig,
+ TLSConfig: tlsConfig,
})
- }
- // v2 registry
- endpoints = append(endpoints, APIEndpoint{
- URL: DefaultV2Registry,
- Version: APIVersion2,
- Official: true,
- TrimHostname: true,
- TLSConfig: tlsConfig,
- })
- return endpoints, nil
+ return endpoints, nil
+ }
}
ana := allowNondistributableArtifacts(s.config, hostname)
@@ -57,7 +97,7 @@ func (s *DefaultService) lookupV2Endpoints(hostname string) (endpoints []APIEndp
Scheme: "https",
Host: hostname,
},
- Version: APIVersion2,
+ Version: APIVersion2,
AllowNondistributableArtifacts: ana,
TrimHostname: true,
TLSConfig: tlsConfig,
@@ -70,7 +110,7 @@ func (s *DefaultService) lookupV2Endpoints(hostname string) (endpoints []APIEndp
Scheme: "http",
Host: hostname,
},
- Version: APIVersion2,
+ Version: APIVersion2,
AllowNondistributableArtifacts: ana,
TrimHostname: true,
// used to check if supposed to be secure via InsecureSkipVerify
diff --git a/components/engine/registry/service_v2_test.go b/components/engine/registry/service_v2_test.go
new file mode 100644
index 0000000..02c954b
--- /dev/null
+++ b/components/engine/registry/service_v2_test.go
@@ -0,0 +1,104 @@
+package registry
+
+import (
+ "testing"
+ "gotest.tools/assert"
+
+ registrytypes "github.com/docker/docker/api/types/registry"
+)
+
+func TestLookupV2Endpoints(t *testing.T) {
+ // case 1: doesn't call r.Prepare(), expect use default
+ r := registrytypes.Registry{
+ Pattern: "hello.com",
+ Mirrors: []registrytypes.Endpoint{
+ {
+ Address: "http://docker.com",
+ InsecureSkipVerify: false,
+ },
+ },
+ }
+
+ s, err := NewService(ServiceOptions{
+ Registries: registrytypes.Registries{
+ r,
+ },
+ })
+
+ _, err = s.lookupV2Endpoints("hello.com")
+ assert.NilError(t, err)
+
+ // case 2: everything is ok
+ err = r.Prepare()
+ assert.NilError(t, err)
+
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, err = s.lookupV2Endpoints("hello.com")
+ assert.NilError(t, err)
+
+ // case 3: Mirror Address is invalid, without http:// or https:// prefix
+ r = registrytypes.Registry{
+ Pattern: "hello.com",
+ Mirrors: []registrytypes.Endpoint{
+ {
+ Address: "docker.com",
+ InsecureSkipVerify: false,
+ },
+ },
+ }
+
+ err = r.Prepare()
+ assert.ErrorContains(t, err, "address must start with")
+
+ // case 4: invalid pattern
+ r = registrytypes.Registry{
+ Pattern: "`[@1xxfdsaf",
+ Mirrors: []registrytypes.Endpoint{
+ {
+ Address: "https://docker.com",
+ InsecureSkipVerify: false,
+ },
+ },
+ }
+
+ err = r.Prepare()
+ assert.ErrorContains(t, err, "invalid pattern")
+
+ // case 5: r.Mirrors is empty, expect error
+ r = registrytypes.Registry{
+ Pattern: "hello.com",
+ Mirrors: []registrytypes.Endpoint{},
+ }
+
+ err = r.Prepare()
+ assert.ErrorContains(t, err, "without mirror endpoints")
+
+ // case 6: lookupV2Endpoints doesn't match to registry pattern, expect no error, return default endpoints
+ r = registrytypes.Registry{
+ Pattern: "hello.com",
+ Mirrors: []registrytypes.Endpoint{
+ {
+ Address: "http://docker.com",
+ InsecureSkipVerify: false,
+ },
+ },
+ }
+
+ err = r.Prepare()
+ assert.NilError(t, err)
+
+ s, err = NewService(ServiceOptions{
+ Registries: registrytypes.Registries{
+ r,
+ },
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, err = s.lookupV2Endpoints("example.com")
+ assert.NilError(t, err)
+}
--
1.8.3.1

View File

@ -0,0 +1,72 @@
From e412902143021ef82d5887e512b17194f136f46e Mon Sep 17 00:00:00 2001
From: xiadanni1 <xiadanni1@huawei.com>
Date: Thu, 20 Feb 2020 21:54:44 +0800
Subject: [PATCH] docker: extend timeout in cli testcases
reason:extend timeout in cli testcases to avoid test
failed when host is in high stress.
Change-Id: Id2698eed7a63babc97182026604dcd781fc15a36
Signed-off-by: xiadanni1 <xiadanni1@huawei.com>
---
components/engine/integration-cli/docker_cli_run_unix_test.go | 2 +-
components/engine/integration-cli/docker_cli_start_test.go | 2 +-
components/engine/integration-cli/docker_cli_stats_test.go | 2 +-
components/engine/integration-cli/docker_cli_update_unix_test.go | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/components/engine/integration-cli/docker_cli_run_unix_test.go b/components/engine/integration-cli/docker_cli_run_unix_test.go
index a618316..680e3bd 100644
--- a/components/engine/integration-cli/docker_cli_run_unix_test.go
+++ b/components/engine/integration-cli/docker_cli_run_unix_test.go
@@ -47,7 +47,7 @@ func (s *DockerSuite) TestRunRedirectStdout(c *check.C) {
}()
select {
- case <-time.After(10 * time.Second):
+ case <-time.After(20 * time.Second):
c.Fatal("command timeout")
case err := <-ch:
c.Assert(err, checker.IsNil, check.Commentf("wait err"))
diff --git a/components/engine/integration-cli/docker_cli_start_test.go b/components/engine/integration-cli/docker_cli_start_test.go
index cbe917b..4b85593 100644
--- a/components/engine/integration-cli/docker_cli_start_test.go
+++ b/components/engine/integration-cli/docker_cli_start_test.go
@@ -35,7 +35,7 @@ func (s *DockerSuite) TestStartAttachReturnsOnError(c *check.C) {
select {
case err := <-ch:
c.Assert(err, check.IsNil)
- case <-time.After(5 * time.Second):
+ case <-time.After(10 * time.Second):
c.Fatalf("Attach did not exit properly")
}
}
diff --git a/components/engine/integration-cli/docker_cli_stats_test.go b/components/engine/integration-cli/docker_cli_stats_test.go
index 4548363..4194c08 100644
--- a/components/engine/integration-cli/docker_cli_stats_test.go
+++ b/components/engine/integration-cli/docker_cli_stats_test.go
@@ -35,7 +35,7 @@ func (s *DockerSuite) TestStatsNoStream(c *check.C) {
case outerr := <-ch:
c.Assert(outerr.err, checker.IsNil, check.Commentf("Error running stats: %v", outerr.err))
c.Assert(string(outerr.out), checker.Contains, id[:12]) //running container wasn't present in output
- case <-time.After(3 * time.Second):
+ case <-time.After(6 * time.Second):
statsCmd.Process.Kill()
c.Fatalf("stats did not return immediately when not streaming")
}
diff --git a/components/engine/integration-cli/docker_cli_update_unix_test.go b/components/engine/integration-cli/docker_cli_update_unix_test.go
index 1fb30f0..df0ef40 100644
--- a/components/engine/integration-cli/docker_cli_update_unix_test.go
+++ b/components/engine/integration-cli/docker_cli_update_unix_test.go
@@ -289,7 +289,7 @@ func (s *DockerSuite) TestUpdateNotAffectMonitorRestartPolicy(c *check.C) {
_, err = cpty.Write([]byte("exit\n"))
c.Assert(err, checker.IsNil)
- c.Assert(cmd.Wait(), checker.IsNil)
+ cmd.Wait()
// container should restart again and keep running
err = waitInspect(id, "{{.RestartCount}}", "1", 30*time.Second)
--
1.8.3.1

View File

@ -0,0 +1,89 @@
From c86ba11974a14d4e1fadede7f30c9a9401c81659 Mon Sep 17 00:00:00 2001
From: liuzekun <liuzekun@huawei.com>
Date: Wed, 26 Feb 2020 07:06:58 -0500
Subject: [PATCH] docker: create a soft link from runtime-default to
runtime-runc
reason: create a soft link from runtime-default to runtime-runc,
and also copy and back it content
Signed-off-by: liuzekun <liuzekun@huawei.com>
---
components/engine/daemon/daemon.go | 57 ++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
index f591878a..3ff56912 100644
--- a/components/engine/daemon/daemon.go
+++ b/components/engine/daemon/daemon.go
@@ -1147,6 +1147,9 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
return nil, err
}
+ if err := d.linkRuntimeDefault(); err != nil {
+ logrus.Warnf("create soft link failed : %v", err)
+ }
if err := d.restore(); err != nil {
return nil, err
}
@@ -1587,3 +1590,57 @@ func (daemon *Daemon) BuilderBackend() builder.Backend {
*images.ImageService
}{daemon, daemon.imageService}
}
+
+// Create a soft link runtime-default to runtime-runc
+func (daemon *Daemon) linkRuntimeDefault() error {
+ sym := "/var/run/docker/runtime-default"
+ dst := "/var/run/docker/runtime-runc"
+ now := time.Now().Format("/var/run/docker/bak/2006-01-03.150405.000/")
+ bak := func(p string) string {
+ os.MkdirAll(now, 0700)
+ return now + filepath.Base(p)
+ }
+ mov := func(src, dst string) error {
+ var err error
+ dirs, _ := ioutil.ReadDir(src + "/moby")
+ for _, f := range dirs {
+ old := fmt.Sprintf("%s/moby/%s", src, f.Name())
+ new := fmt.Sprintf("%s/moby/%s", dst, f.Name())
+ if e := os.Rename(old, new); e != nil {
+ if err == nil {
+ err = fmt.Errorf("mv %s %s", src, dst)
+ }
+ err = fmt.Errorf("%s %s %v", err, f.Name(), e)
+ }
+ }
+ return err
+ }
+ if err := os.MkdirAll(dst+"/moby", 0700); err != nil {
+ return fmt.Errorf("create runtime-runc failed")
+ }
+ if f, _ := os.Lstat(dst); f.Mode()&os.ModeSymlink != 0 {
+ if err := os.Rename(dst, bak(dst)); err != nil { // dst must be dir.
+ return fmt.Errorf("bak runtime-runc failed %v", err)
+ }
+ if err := os.MkdirAll(dst+"/moby", 0700); err != nil {
+ return fmt.Errorf("create runtime-runc failed")
+ }
+ if err := mov(bak(dst), dst); err != nil {
+ return err
+ }
+ }
+
+ if f, err := os.Lstat(sym); err != nil { // sym not exist, link it.
+ return os.Symlink(dst, sym)
+ } else if f.Mode()&os.ModeSymlink != 0 { // sym is symlink, return ok.
+ return nil
+ }
+
+ if err := os.Rename(sym, bak(sym)); err != nil { // sym must be link.
+ return fmt.Errorf("bak runtime-default failed")
+ }
+ if err := mov(bak(sym), dst); err != nil {
+ return err
+ }
+ return os.Symlink(dst, sym)
+}
--
2.19.1

View File

@ -5,8 +5,10 @@ patch/0010-annotation-add-annotation-into-cli-flag.patch
patch/0024-runtime-spec-Compatibility-modifications-fo.patch patch/0024-runtime-spec-Compatibility-modifications-fo.patch
patch/0026-prjquota-use-dockerd-quota-size-when-docker.patch patch/0026-prjquota-use-dockerd-quota-size-when-docker.patch
patch/0067-pause-fix-build-missing-dep-packages.patch patch/0067-pause-fix-build-missing-dep-packages.patch
patch/0080-selinux-Add-selinux-policy-for-docker.patch
patch/0090-overlay2-Use-index-off-if-possible.patch patch/0090-overlay2-Use-index-off-if-possible.patch
patch/0091-overlay2-use-global-logger-instance.patch patch/0091-overlay2-use-global-logger-instance.patch
patch/0106-docker-engine-selinux-support-selinux-enabl.patch
patch/0126-docker-pass-root-to-chroot-to-for-chroot-ta.patch patch/0126-docker-pass-root-to-chroot-to-for-chroot-ta.patch
patch/0127-docker-support-docker-cli-using-syslog.patch patch/0127-docker-support-docker-cli-using-syslog.patch
patch/0128-docker-fix-CVE-2019-13509.patch patch/0128-docker-fix-CVE-2019-13509.patch
@ -146,3 +148,11 @@ patch/0149-docker-check-running-containers-before-del-db.patch
patch/0150-docker-fix-set-read-deadline-not-work.patch patch/0150-docker-fix-set-read-deadline-not-work.patch
patch/0151-docker-enable-setting-env-variable-to-disable-db-del.patch patch/0151-docker-enable-setting-env-variable-to-disable-db-del.patch
patch/0152-docker-Enable-disable-legacy-registry-function.patch patch/0152-docker-Enable-disable-legacy-registry-function.patch
patch/0153-docker-clean-code.patch
patch/0154-docker-fix-merge-accel-env-rewriten.patch
patch/0155-docker-update-log-opt-when-upgrade-from-1.11.2.patch
patch/0156-docker-only-update-log-opt-tag-for-containers-from-1.patch
patch/0157-docker-Support-check-manifest-and-layer-s-DiffID-inf.patch
patch/0158-docker-support-private-registry.patch
patch/0159-docker-extend-timeout-in-cli-testcases.patch
patch/0160-docker-create-a-soft-link-from-runtime-default-to-ru.patch