diff --git a/README.md b/README.md index 298436198..87e7c7c0d 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,14 @@ your system. See more details in [Checkpoint and Restore](#checkpoint-and-restor Build requirements for developers are listed in [BUILDING](BUILDING.md). + +## Supported Registries + +Any registry which is compliant with the [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec) +is supported by containerd. + +For configuring registries, see [registry host configuration documentation](docs/hosts.md) + ## Features ### Client diff --git a/docs/hosts.md b/docs/hosts.md index 7f2217183..d713af9ca 100644 --- a/docs/hosts.md +++ b/docs/hosts.md @@ -5,6 +5,14 @@ Configuring registries will be done by specifying (optionally) a `hosts.toml` fi each desired registry host in a configuration directory. **Note**: Updates under this directory do not require restarting the containerd daemon. +## Registry API Support + +All configured registry hosts are expected to comply with the [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec). +Registries which are non-compliant or implement non-standard behavior are not guaranteed +to be supported and may break unexpectedly between releases. + +Currently supported OCI Distribution version: **[v1.0.0](https://github.com/opencontainers/distribution-spec/tree/v1.0.0)** + ## Specifying the Configuration Directory ### Using Host Namespace Configs with CTR @@ -235,8 +243,10 @@ client = [["/etc/certs/client.cert", "/etc/certs/client.key"],["/etc/certs/clien ## skip_verify field -`skip_verify` set this flag to `true` to skip the registry certificate -verification for this registry host namespace. (Defaults to `false`) +`skip_verify` skips verifications of the registry's certificate chain and +host name when set to `true`. This should only be used for testing or in +combination with other method of verifying connections. (Defaults to `false`) + ``` skip_verify = false ``` @@ -264,6 +274,17 @@ or x-custom-1-2 = "another custom header" ``` +## override_path field + +`override_path` is used to indicate the host's API root endpoint is defined +in the URL path rather than by the API specification. This may be used with +non-compliant OCI registries which are missing the `/v2` prefix. +(Defaults to `false`) + +``` +override_path = true +``` + ## host field(s) (in the toml table format) `[host]."https://namespace"` and `[host].http://namespace` entries in the @@ -300,6 +321,10 @@ for this registry host namespace: [host."https://test-3.registry"] client = ["/etc/certs/client-1.pem", "/etc/certs/client-2.pem"] + +[host."https://non-compliant-mirror.registry/v2/upstream"] + capabilities = ["pull"] + override_path = true ``` **Note**: Recursion is not supported in the specification of host mirror diff --git a/remotes/docker/config/hosts.go b/remotes/docker/config/hosts.go index b24ba33f5..40330f17e 100644 --- a/remotes/docker/config/hosts.go +++ b/remotes/docker/config/hosts.go @@ -54,8 +54,6 @@ type hostConfig struct { header http.Header - // TODO: API ("docker" or "oci") - // TODO: API Version ("v1", "v2") // TODO: Add credential configuration (domain alias, username) } @@ -283,19 +281,34 @@ type hostFileConfig struct { // - push Capabilities []string `toml:"capabilities"` - // CACert can be a string or an array of strings + // CACert are the public key certificates for TLS + // Accepted types + // - string - Single file with certificate(s) + // - []string - Multiple files with certificates CACert interface{} `toml:"ca"` - // TODO: Make this an array (two key types, one for pairs (multiple files), one for single file?) + // Client keypair(s) for TLS with client authentication + // Accepted types + // - string - Single file with public and private keys + // - []string - Multiple files with public and private keys + // - [][2]string - Multiple keypairs with public and private keys in separate files Client interface{} `toml:"client"` + // SkipVerify skips verification of the server's certificate chain + // and host name. This should only be used for testing or in + // combination with other methods of verifying connections. SkipVerify *bool `toml:"skip_verify"` + // Header are additional header files to send to the server Header map[string]interface{} `toml:"header"` - // API (default: "docker") - // API Version (default: "v2") - // Credentials: helper? name? username? alternate domain? token? + // OverridePath indicates the API root endpoint is defined in the URL + // path rather than by the API specification. + // This may be used with non-compliant OCI registries to override the + // API root endpoint. + OverridePath bool `toml:"override_path"` + + // TODO: Credentials: helper? name? username? alternate domain? token? } func parseHostsFile(baseDir string, b []byte) ([]hostConfig, error) { @@ -367,16 +380,12 @@ func parseHostConfig(server string, baseDir string, config hostFileConfig) (host } result.scheme = u.Scheme result.host = u.Host - // TODO: Handle path based on registry protocol - // Define a registry protocol type - // OCI v1 - Always use given path as is - // Docker v2 - Always ensure ends with /v2/ if len(u.Path) > 0 { u.Path = path.Clean(u.Path) - if !strings.HasSuffix(u.Path, "/v2") { + if !strings.HasSuffix(u.Path, "/v2") && !config.OverridePath { u.Path = u.Path + "/v2" } - } else { + } else if !config.OverridePath { u.Path = "/v2" } result.path = u.Path diff --git a/remotes/docker/config/hosts_test.go b/remotes/docker/config/hosts_test.go index 18dc1c659..44586fa5e 100644 --- a/remotes/docker/config/hosts_test.go +++ b/remotes/docker/config/hosts_test.go @@ -104,6 +104,13 @@ ca = "/etc/path/default" [host."https://test-3.registry"] client = ["/etc/certs/client-1.pem", "/etc/certs/client-2.pem"] + +[host."https://noncompliantmirror.registry/v2/namespaceprefix"] + capabilities = ["pull"] + override_path = true + +[host."https://noprefixnoncompliant.registry"] + override_path = true ` var tb, fb = true, false expected := []hostConfig{ @@ -159,6 +166,17 @@ ca = "/etc/path/default" {filepath.FromSlash("/etc/certs/client-2.pem")}, }, }, + { + scheme: "https", + host: "noncompliantmirror.registry", + path: "/v2/namespaceprefix", + capabilities: docker.HostCapabilityPull, + }, + { + scheme: "https", + host: "noprefixnoncompliant.registry", + capabilities: allCaps, + }, { scheme: "https", host: "test-default.registry",