Compare commits

...

40 Commits

Author SHA1 Message Date
Sebastiaan van Stijn
71fa3ab079 Merge pull request #47196 from akerouanton/25.0-fix-multiple-rename-error
[25.0] daemon: rename: don't reload endpoint from datastore
2024-01-23 23:56:39 +01:00
Albin Kerouanton
5295e88ceb daemon: rename: don't reload endpoint from datastore
Commit 8b7af1d0f added some code to update the DNSNames of all
endpoints attached to a sandbox by loading a new instance of each
affected endpoints from the datastore through a call to
`Network.EndpointByID()`.

This method then calls `Network.getEndpointFromStore()`, that in
turn calls `store.GetObject()`, which then calls `cache.get()`,
which calls `o.CopyTo(kvObject)`. This effectively creates a fresh
new instance of an Endpoint. However, endpoints are already kept in
memory by Sandbox, meaning we now have two in-memory instances of
the same Endpoint.

As it turns out, libnetwork is built around the idea that no two objects
representing the same thing should leave in-memory, otherwise breaking
mutex locking and optimistic locking (as both instances will have a drifting
version tracking ID -- dbIndex in libnetwork parliance).

In this specific case, this bug materializes by container rename failing
when applied a second time for a given container. An integration test is
added to make sure this won't happen again.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
(cherry picked from commit 80c44b4b2e)
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2024-01-23 22:53:43 +01:00
Paweł Gronowski
6eef840b8a Merge pull request #47191 from vvoland/volume-cifs-resolve-optout-25
[25.0 backport] volume/local: Make host resolution backwards compatible
2024-01-23 19:13:39 +01:00
Sebastiaan van Stijn
e2ab4718c8 Merge pull request #47182 from akerouanton/25.0-fix-aliases-on-default-bridge
[25.0] daemon: only add short cid to aliases for custom networks
2024-01-23 18:28:58 +01:00
Paweł Gronowski
3de920a0b1 volume/local: Fix cifs url containing spaces
Unescapes the URL to avoid passing an URL encoded address to the kernel.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 250886741b)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-01-23 17:46:23 +01:00
Paweł Gronowski
a445aa95e5 volume/local: Add tests for parsing nfs/cifs mounts
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit f4beb130b0)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-01-23 17:46:18 +01:00
Paweł Gronowski
cb77e48229 volume/local: Break early if addr was specified
I made a mistake in the last commit - after resolving the IP from the
passed `addr` for CIFS it would still resolve the `device` part.

Apply only one name resolution

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit df43311f3d)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-01-23 17:45:09 +01:00
Albin Kerouanton
e8801fbe26 daemon: only add short cid to aliases for custom networks
Prior to 7a9b680a, the container short ID was added to the network
aliases only for custom networks. However, this logic wasn't preserved
in 6a2542d and now the cid is always added to the list of network
aliases.

This commit reintroduces the old logic.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
(cherry picked from commit 9f37672ca8)
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2024-01-23 17:09:11 +01:00
Sebastiaan van Stijn
613b6a12c1 Merge pull request #47192 from thaJeztah/25.0_backport_fix_gateway_ip
[25.0 backport] fix "host-gateway-ip" label not set for builder workers
2024-01-23 17:05:02 +01:00
Sebastiaan van Stijn
1b6738369f Merge pull request #47189 from vvoland/c8d-prefer-default-platform-snapshot-25
[25.0 release] c8d/snapshot: Create any platform if not specified
2024-01-23 16:17:16 +01:00
Sebastiaan van Stijn
b8cc2e8c66 fix "host-gateway-ip" label not set for builder workers
Commit 21e50b89c9 added a label on the buildkit
worker to advertise the host-gateway-ip. This option can be either set by the
user in the daemon config, or otherwise defaults to the gateway-ip.

If no value is set by the user, discovery of the gateway-ip happens when
initializing the network-controller (`NewDaemon`, `daemon.restore()`).

However d222bf097c changed how we handle the
daemon config. As a result, the `cli.Config` used when initializing the
builder only holds configuration information form the daemon config
(user-specified or defaults), but is not updated with information set
by `NewDaemon`.

This patch adds an accessor on the daemon to get the current daemon config.
An alternative could be to return the config by `NewDaemon` (which should
likely be a _copy_ of the config).

Before this patch:

    docker buildx inspect default
    Name:   default
    Driver: docker

    Nodes:
    Name:      default
    Endpoint:  default
    Status:    running
    Buildkit:  v0.12.4+3b6880d2a00f
    Platforms: linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
    Labels:
     org.mobyproject.buildkit.worker.moby.host-gateway-ip: <nil>

After this patch:

    docker buildx inspect default
    Name:   default
    Driver: docker

    Nodes:
    Name:      default
    Endpoint:  default
    Status:    running
    Buildkit:  v0.12.4+3b6880d2a00f
    Platforms: linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
    Labels:
     org.mobyproject.buildkit.worker.moby.host-gateway-ip: 172.18.0.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 00c9785e2e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-23 15:59:09 +01:00
Paweł Gronowski
fcccfeb811 c8d/snapshot: Create any platform if not specified
With containerd snapshotters enabled `docker run` currently fails when
creating a container from an image that doesn't have the default host
platform without an explicit `--platform` selection:

```
$ docker run image:amd64
Unable to find image 'asdf:amd64' locally
docker: Error response from daemon: pull access denied for asdf, repository does not exist or may require 'docker login'.
See 'docker run --help'.
```

This is confusing and the graphdriver behavior is much better here,
because it runs whatever platform the image has, but prints a warning:

```
$ docker run image:amd64
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
```

This commits changes the containerd snapshotter behavior to be the same
as the graphdriver. This doesn't affect container creation when platform
is specified explicitly.

```
$ docker run --rm --platform linux/arm64 asdf:amd64
Unable to find image 'asdf:amd64' locally
docker: Error response from daemon: pull access denied for asdf, repository does not exist or may require 'docker login'.
See 'docker run --help'.
```

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit e438db19d56bef55f9676af9db46cc04caa6330b)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-01-23 15:05:54 +01:00
Sebastiaan van Stijn
f8eaa14a18 pkg/platforms: internalize in daemon/containerd
This matcher was only used internally in the containerd implementation of
the image store. Un-export it, and make it a local utility in that package
to prevent external use.

This package was introduced in 1616a09b61
(v24.0), and there are no known external consumers of this package, so there
should be no need to deprecate / alias the old location.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 94b4765363)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-01-23 15:05:50 +01:00
Paweł Gronowski
ac76925ff2 volume/local: Make host resolution backwards compatible
Commit 8ae94cafa5 added a DNS resolution
of the `device` part of the volume option.

The previous way to resolve the passed hostname was to use `addr`
option, which was handled by the same code path as the `nfs` mount type.

The issue is that `addr` is also an SMB module option handled by kernel
and passing a hostname as `addr` produces an invalid argument error.

To fix that, restore the old behavior to handle `addr` the same way as
before, and only perform the new DNS resolution of `device` if there is
no `addr` passed.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 0d51cf9db8)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-01-23 15:01:44 +01:00
Akihiro Suda
c7a1d928c0 Merge pull request #47180 from thaJeztah/25.0_backport_update_compose
[25.0 backport] Dockerfile: update docker compose to v2.24.2
2024-01-23 22:08:15 +09:00
Sebastiaan van Stijn
2672baefd7 Merge pull request #47178 from thaJeztah/25.0_backport_richer_xattr_errors
[25.0 backport] pkg/system: return even richer xattr errors
2024-01-23 10:56:46 +01:00
Sebastiaan van Stijn
ff15b49b47 Dockerfile: update docker compose to v2.24.2
Update the version of compose used in CI to the latest version.

- full diff: docker/compose@v2.24.1...v2.24.2
- release notes: https://github.com/docker/compose/releases/tag/v2.24.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 05d952b246)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-23 10:25:49 +01:00
Cory Snider
c0573b133f pkg/system: return even richer xattr errors
The names of extended attributes are not completely freeform. Attributes
are namespaced, and the kernel enforces (among other things) that only
attributes whose names are prefixed with a valid namespace are
permitted. The name of the attribute therefore needs to be known in
order to diagnose issues with lsetxattr. Include the name of the
extended attribute in the errors returned from the Lsetxattr and
Lgetxattr so users and us can more easily troubleshoot xattr-related
issues. Include the name in a separate rich-error field to provide code
handling the error enough information to determine whether or not the
failure can be ignored.

Signed-off-by: Cory Snider <csnider@mirantis.com>
(cherry picked from commit 43bf65c174)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-23 09:27:49 +01:00
Sebastiaan van Stijn
c7466c0b52 Merge pull request #47170 from thaJeztah/25.0_backport_remove_deprecated_api_docs
[25.0 backport] docs: remove documentation for deprecated API versions (v1.23 and before)
2024-01-22 21:45:09 +01:00
Sebastiaan van Stijn
dde33d0dfe Merge pull request #47172 from thaJeztah/25.0_backport_fix-bad-http-code
[25.0 backport] daemon: return an InvalidParameter error when ep settings are wrong
2024-01-22 21:44:38 +01:00
Sebastiaan van Stijn
39fedb254b Merge pull request #47169 from thaJeztah/25.0_backport_test_fixes
[25.0 backport] backport test-fixes
2024-01-22 21:20:37 +01:00
Sebastiaan van Stijn
f0f5fc974a Merge pull request #47171 from thaJeztah/25.0_backport_47146-duplicate_mac_addrs
[25.0 backport] Remove generated MAC addresses on restart.
2024-01-22 20:53:52 +01:00
Albin Kerouanton
7c185a1e40 daemon: return an InvalidParameter error when ep settings are wrong
Since v25.0 (commit ff50388), we validate endpoint settings when
containers are created, instead of doing so when containers are started.
However, a container created prior to that release would still trigger
validation error at start-time. In such case, the API returns a 500
status code because the Go error isn't wrapped into an InvalidParameter
error. This is now fixed.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
(cherry picked from commit fcc651972e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-22 20:50:10 +01:00
Rob Murray
2b036fb1da Remove generated MAC addresses on restart.
The MAC address of a running container was stored in the same place as
the configured address for a container.

When starting a stopped container, a generated address was treated as a
configured address. If that generated address (based on an IPAM-assigned
IP address) had been reused, the containers ended up with duplicate MAC
addresses.

So, remember whether the MAC address was explicitly configured, and
clear it if not.

Signed-off-by: Rob Murray <rob.murray@docker.com>
(cherry picked from commit cd53b7380c)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-22 19:51:54 +01:00
Sebastiaan van Stijn
1f24da70d8 docs/api: remove version matrices from swagger files
These tables linked to deprecated API versions, and an up-to-date version of
the matrix is already included at https://docs.docker.com/engine/api/#api-version-matrix

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 521123944a)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-22 19:44:48 +01:00
Sebastiaan van Stijn
358fecb566 docs: remove documentation for deprecated API versions < v1.23
These versions are deprecated in v25.0.0, and disabled by default,
see 08e4e88482.

Users that need to refer to documentation for older API versions,
can use archived versions of the documentation on GitHub:

- API v1.23 and before: https://github.com/moby/moby/tree/v25.0.0/docs/api
- API v1.17 and before: https://github.com/moby/moby/tree/v1.9.1/docs/reference/api

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit d54be2ee6d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-22 19:44:48 +01:00
Sebastiaan van Stijn
f030b25770 Dockerfile: update docker compose to v2.24.1
Update the version of compose used in CI to the latest version.

- full diff: https://github.com/docker/compose/compare/v2.24.0...v2.24.1
- release notes: https://github.com/docker/compose/releases/tag/v2.24.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 307fe9c716)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-22 19:41:15 +01:00
Sebastiaan van Stijn
e07aed0f77 Dockerfile: update dev-shell version of the cli to v25.0.0
Update the docker CLI that's available for debugging in the dev-shell
to the v25 release.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit dfced4b557)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-22 19:41:15 +01:00
Sebastiaan van Stijn
cdf3611cff integration-cli: TestInspectAPIMultipleNetworks: use current version
This test was added in f301c5765a to test
inspect output for API > v1.21, however, it was pinned to API v1.21,
which is now deprecated.

Remove the fixed version, as the intent was to test "current" API versions
(API v1.21 and up),

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit a0466ca8e1)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-22 19:40:57 +01:00
Sebastiaan van Stijn
05267e9e8c integration-cli: TestInspectAPIBridgeNetworkSettings121: use current version
This test was added in f301c5765a to test
inspect output for API > v1.21, however, it was pinned to API v1.21,
which is now deprecated.

Remove the fixed version, as the intent was to test "current" API versions
(API v1.21 and up),

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 13a384a6fa)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-22 19:40:56 +01:00
Sebastiaan van Stijn
e5edf62bca integration-cli: TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRootfs: use current API
This test was added in 75f6929b44, but pinned
to the API version that was current at the time (v1.20), which is now
deprecated.

Update the test to use the current API version.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 52e3fff828)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-22 19:40:42 +01:00
Sebastiaan van Stijn
e14d121d49 Merge pull request #47163 from vvoland/25-fix-swarm-startinterval-25
[25.0 backport] daemon/cluster/executer: Add missing `StartInterval`
2024-01-22 18:39:43 +01:00
Paweł Gronowski
e0acf1cd70 daemon/cluster/executer: Add missing StartInterval
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 6100190e5c)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-01-22 15:23:27 +01:00
Sebastiaan van Stijn
c2847b2eb2 Merge pull request #47136 from thaJeztah/25.0_backport_git-url-regex
[25.0 backport] Fix isGitURL regular expression
2024-01-22 15:14:04 +01:00
Sebastiaan van Stijn
0894f7fe69 Merge pull request #47161 from vvoland/save-fix-oci-diffids-25
[25.0 backport] image/save: Fix layers order in OCI manifest
2024-01-22 15:05:20 +01:00
Sebastiaan van Stijn
d25aa32c21 Merge pull request #47135 from thaJeztah/25.0_backport_allow-container-ip-outside-subpool
[25.0 backport] libnetwork: loosen container IPAM validation
2024-01-22 14:05:17 +01:00
Paweł Gronowski
1e335cfa74 image/save: Fix layers order in OCI manifest
Order the layers in OCI manifest by their actual apply order. This is
required by the OCI image spec.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 17fd6562bf)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-01-22 13:53:02 +01:00
Paweł Gronowski
4d287e9267 image/save: Change layers type to DiffID
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 4979605212)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-01-22 13:52:57 +01:00
David Dooling
0240f5675b Fix isGitURL regular expression
Escape period (.) so regular expression does not match any character before "git".

Signed-off-by: David Dooling <david.dooling@docker.com>
(cherry picked from commit 768146b1b0)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-20 12:19:07 +01:00
Cory Snider
13964248f1 libnetwork: loosen container IPAM validation
Permit container network attachments to set any static IP address within
the network's IPAM master pool, including when a subpool is configured.
Users have come to depend on being able to statically assign container
IP addresses which are guaranteed not to collide with automatically-
assigned container addresses.

Signed-off-by: Cory Snider <csnider@mirantis.com>
(cherry picked from commit 058b30023f)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-20 11:33:04 +01:00
51 changed files with 421 additions and 16876 deletions

View File

@@ -8,12 +8,12 @@ ARG XX_VERSION=1.2.1
ARG VPNKIT_VERSION=0.5.0
ARG DOCKERCLI_REPOSITORY="https://github.com/docker/cli.git"
ARG DOCKERCLI_VERSION=v24.0.2
ARG DOCKERCLI_VERSION=v25.0.0
# cli version used for integration-cli tests
ARG DOCKERCLI_INTEGRATION_REPOSITORY="https://github.com/docker/cli.git"
ARG DOCKERCLI_INTEGRATION_VERSION=v17.06.2-ce
ARG BUILDX_VERSION=0.12.1
ARG COMPOSE_VERSION=v2.24.0
ARG COMPOSE_VERSION=v2.24.2
ARG SYSTEMD="false"
ARG DOCKER_STATIC=1

View File

@@ -9,6 +9,7 @@ import (
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/longpath"
"github.com/docker/docker/pkg/system"
"github.com/docker/docker/pkg/tarsum"
"github.com/moby/sys/symlink"
"github.com/pkg/errors"
@@ -24,9 +25,11 @@ func (c *archiveContext) Close() error {
}
func convertPathError(err error, cleanpath string) error {
if err, ok := err.(*os.PathError); ok {
switch err := err.(type) {
case *os.PathError:
err.Path = cleanpath
case *system.XattrError:
err.Path = cleanpath
return err
}
return err
}

View File

@@ -12,7 +12,7 @@ import (
// urlPathWithFragmentSuffix matches fragments to use as Git reference and build
// context from the Git repository. See IsGitURL for details.
var urlPathWithFragmentSuffix = regexp.MustCompile(".git(?:#.+)?$")
var urlPathWithFragmentSuffix = regexp.MustCompile(`\.git(?:#.+)?$`)
// IsURL returns true if the provided str is an HTTP(S) URL by checking if it
// has a http:// or https:// scheme. No validation is performed to verify if the

View File

@@ -17,6 +17,7 @@ var (
}
invalidGitUrls = []string{
"http://github.com/docker/docker.git:#branch",
"https://github.com/docker/dgit",
}
)

View File

@@ -301,7 +301,13 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) {
routerCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
routerOptions, err := newRouterOptions(routerCtx, cli.Config, d)
// Get a the current daemon config, because the daemon sets up config
// during initialization. We cannot user the cli.Config for that reason,
// as that only holds the config that was set by the user.
//
// FIXME(thaJeztah): better separate runtime and config data?
daemonCfg := d.Config()
routerOptions, err := newRouterOptions(routerCtx, &daemonCfg, d)
if err != nil {
return err
}

View File

@@ -377,12 +377,14 @@ func (c *containerConfig) healthcheck() *enginecontainer.HealthConfig {
interval, _ := gogotypes.DurationFromProto(hcSpec.Interval)
timeout, _ := gogotypes.DurationFromProto(hcSpec.Timeout)
startPeriod, _ := gogotypes.DurationFromProto(hcSpec.StartPeriod)
startInterval, _ := gogotypes.DurationFromProto(hcSpec.StartInterval)
return &enginecontainer.HealthConfig{
Test: hcSpec.Test,
Interval: interval,
Timeout: timeout,
Retries: int(hcSpec.Retries),
StartPeriod: startPeriod,
Test: hcSpec.Test,
Interval: interval,
Timeout: timeout,
Retries: int(hcSpec.Retries),
StartPeriod: startPeriod,
StartInterval: startInterval,
}
}

View File

@@ -637,6 +637,9 @@ func cleanOperationalData(es *network.EndpointSettings) {
if es.IPAMOperational {
es.IPAMConfig = nil
}
if es.MACOperational {
es.MacAddress = ""
}
}
func (daemon *Daemon) updateNetworkConfig(container *container.Container, n *libnetwork.Network, endpointConfig *networktypes.EndpointSettings, updateSettings bool) error {
@@ -645,7 +648,7 @@ func (daemon *Daemon) updateNetworkConfig(container *container.Container, n *lib
}
if err := validateEndpointSettings(n, n.Name(), endpointConfig); err != nil {
return err
return errdefs.InvalidParameter(err)
}
if updateSettings {
@@ -708,6 +711,7 @@ func (daemon *Daemon) connectToNetwork(cfg *config.Config, container *container.
}
var operIPAM bool
operMAC := true
if nwCfg != nil {
if epConfig, ok := nwCfg.EndpointsConfig[nwName]; ok {
if endpointConfig.IPAMConfig == nil || (endpointConfig.IPAMConfig.IPv4Address == "" && endpointConfig.IPAMConfig.IPv6Address == "" && len(endpointConfig.IPAMConfig.LinkLocalIPs) == 0) {
@@ -717,6 +721,11 @@ func (daemon *Daemon) connectToNetwork(cfg *config.Config, container *container.
// copy IPAMConfig and NetworkID from epConfig via AttachNetwork
endpointConfig.IPAMConfig = epConfig.IPAMConfig
endpointConfig.NetworkID = epConfig.NetworkID
// Work out whether the MAC address is user-configured.
operMAC = endpointConfig.MacAddress == ""
// Copy the configured MAC address (which may be empty).
endpointConfig.MacAddress = epConfig.MacAddress
}
}
@@ -746,6 +755,7 @@ func (daemon *Daemon) connectToNetwork(cfg *config.Config, container *container.
container.NetworkSettings.Networks[nwName] = &network.EndpointSettings{
EndpointSettings: endpointConfig,
IPAMOperational: operIPAM,
MACOperational: operMAC,
}
delete(container.NetworkSettings.Networks, n.ID())

View File

@@ -12,7 +12,7 @@ import (
cerrdefs "github.com/containerd/containerd/errdefs"
containerdimages "github.com/containerd/containerd/images"
cplatforms "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/platforms"
"github.com/containerd/log"
"github.com/distribution/reference"
imagetype "github.com/docker/docker/api/types/image"
@@ -20,7 +20,6 @@ import (
"github.com/docker/docker/errdefs"
"github.com/docker/docker/image"
imagespec "github.com/docker/docker/image/spec/specs-go/v1"
"github.com/docker/docker/pkg/platforms"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@@ -38,9 +37,9 @@ func (i *ImageService) GetImage(ctx context.Context, refOrID string, options ima
return nil, err
}
platform := platforms.AllPlatformsWithPreference(cplatforms.Default())
platform := matchAllWithPreference(platforms.Default())
if options.Platform != nil {
platform = cplatforms.OnlyStrict(*options.Platform)
platform = platforms.OnlyStrict(*options.Platform)
}
var presentImages []imagespec.DockerOCIImage
@@ -158,9 +157,9 @@ func (i *ImageService) GetImage(ctx context.Context, refOrID string, options ima
}
func (i *ImageService) GetImageManifest(ctx context.Context, refOrID string, options imagetype.GetImageOpts) (*ocispec.Descriptor, error) {
platform := platforms.AllPlatformsWithPreference(cplatforms.Default())
platform := matchAllWithPreference(platforms.Default())
if options.Platform != nil {
platform = cplatforms.Only(*options.Platform)
platform = platforms.Only(*options.Platform)
}
cs := i.client.ContentStore()
@@ -188,9 +187,9 @@ func (i *ImageService) GetImageManifest(ctx context.Context, refOrID string, opt
if options.Platform != nil {
if plat == nil {
return nil, errdefs.NotFound(errors.Errorf("image with reference %s was found but does not match the specified platform: wanted %s, actual: nil", refOrID, cplatforms.Format(*options.Platform)))
return nil, errdefs.NotFound(errors.Errorf("image with reference %s was found but does not match the specified platform: wanted %s, actual: nil", refOrID, platforms.Format(*options.Platform)))
} else if !platform.Match(*plat) {
return nil, errdefs.NotFound(errors.Errorf("image with reference %s was found but does not match the specified platform: wanted %s, actual: %s", refOrID, cplatforms.Format(*options.Platform), cplatforms.Format(*plat)))
return nil, errdefs.NotFound(errors.Errorf("image with reference %s was found but does not match the specified platform: wanted %s, actual: %s", refOrID, platforms.Format(*options.Platform), platforms.Format(*plat)))
}
}
@@ -219,7 +218,7 @@ func (i *ImageService) GetImageManifest(ctx context.Context, refOrID string, opt
}
// size returns the total size of the image's packed resources.
func (i *ImageService) size(ctx context.Context, desc ocispec.Descriptor, platform cplatforms.MatchComparer) (int64, error) {
func (i *ImageService) size(ctx context.Context, desc ocispec.Descriptor, platform platforms.MatchComparer) (int64, error) {
var size int64
cs := i.client.ContentStore()

View File

@@ -12,7 +12,7 @@ import (
containerdimages "github.com/containerd/containerd/images"
"github.com/containerd/containerd/images/archive"
"github.com/containerd/containerd/leases"
cplatforms "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/platforms"
"github.com/containerd/log"
"github.com/distribution/reference"
"github.com/docker/docker/api/types/events"
@@ -20,7 +20,6 @@ import (
"github.com/docker/docker/daemon/images"
"github.com/docker/docker/errdefs"
dockerarchive "github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/platforms"
"github.com/docker/docker/pkg/streamformatter"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@@ -49,7 +48,7 @@ func (i *ImageService) PerformWithBaseFS(ctx context.Context, c *container.Conta
//
// TODO(thaJeztah): produce JSON stream progress response and image events; see https://github.com/moby/moby/issues/43910
func (i *ImageService) ExportImage(ctx context.Context, names []string, outStream io.Writer) error {
platform := platforms.AllPlatformsWithPreference(cplatforms.Default())
platform := matchAllWithPreference(platforms.Default())
opts := []archive.ExportOpt{
archive.WithSkipNonDistributableBlobs(),
@@ -236,7 +235,7 @@ func (i *ImageService) LoadImage(ctx context.Context, inTar io.ReadCloser, outSt
opts := []containerd.ImportOpt{
// TODO(vvoland): Allow user to pass platform
containerd.WithImportPlatform(cplatforms.All),
containerd.WithImportPlatform(platforms.All),
containerd.WithSkipMissing(),

View File

@@ -6,12 +6,11 @@ import (
"github.com/containerd/containerd/images"
containerdimages "github.com/containerd/containerd/images"
cplatforms "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/platforms"
"github.com/containerd/log"
"github.com/distribution/reference"
imagetype "github.com/docker/docker/api/types/image"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/platforms"
"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/identity"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -28,7 +27,7 @@ func (i *ImageService) ImageHistory(ctx context.Context, name string) ([]*imaget
cs := i.client.ContentStore()
// TODO: pass platform in from the CLI
platform := platforms.AllPlatformsWithPreference(cplatforms.Default())
platform := matchAllWithPreference(platforms.Default())
var presentImages []ocispec.Image
err = i.walkImageManifests(ctx, img, func(img *ImageManifest) error {

View File

@@ -8,7 +8,7 @@ import (
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/images"
containerdimages "github.com/containerd/containerd/images"
cplatforms "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/platforms"
"github.com/docker/docker/errdefs"
"github.com/moby/buildkit/util/attestation"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -65,7 +65,7 @@ func (i *ImageService) NewImageManifest(ctx context.Context, img containerdimage
parent := img.Target
img.Target = manifestDesc
c8dImg := containerd.NewImageWithPlatform(i.client, img, cplatforms.All)
c8dImg := containerd.NewImageWithPlatform(i.client, img, platforms.All)
return &ImageManifest{
Image: c8dImg,
RealTarget: parent,
@@ -122,7 +122,7 @@ func (im *ImageManifest) Manifest(ctx context.Context) (ocispec.Manifest, error)
func (im *ImageManifest) CheckContentAvailable(ctx context.Context) (bool, error) {
// The target is already a platform-specific manifest, so no need to match platform.
pm := cplatforms.All
pm := platforms.All
available, _, _, missing, err := containerdimages.Check(ctx, im.ContentStore(), im.Target(), pm)
if err != nil {

View File

@@ -28,7 +28,7 @@ func (i *ImageService) PrepareSnapshot(ctx context.Context, id string, parentIma
cs := i.client.ContentStore()
matcher := platforms.Default()
matcher := matchAllWithPreference(platforms.Default())
if platform != nil {
matcher = platforms.Only(*platform)
}

View File

@@ -1,17 +1,17 @@
package platforms
package containerd
import (
cplatforms "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/platforms"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
type allPlatformsWithPreferenceMatcher struct {
preferred cplatforms.MatchComparer
preferred platforms.MatchComparer
}
// AllPlatformsWithPreference will return a platform matcher that matches all
// matchAllWithPreference will return a platform matcher that matches all
// platforms but will order platforms matching the preferred matcher first.
func AllPlatformsWithPreference(preferred cplatforms.MatchComparer) cplatforms.MatchComparer {
func matchAllWithPreference(preferred platforms.MatchComparer) platforms.MatchComparer {
return allPlatformsWithPreferenceMatcher{
preferred: preferred,
}

View File

@@ -180,6 +180,11 @@ func (daemon *Daemon) config() *configStore {
return cfg
}
// Config returns daemon's config.
func (daemon *Daemon) Config() config.Config {
return daemon.config().Config
}
// HasExperimental returns whether the experimental features of the daemon are enabled or not
func (daemon *Daemon) HasExperimental() bool {
return daemon.config().Experimental

View File

@@ -8,6 +8,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
containertypes "github.com/docker/docker/api/types/container"
networktypes "github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/api/types/versions/v1p20"
@@ -36,8 +37,10 @@ func (daemon *Daemon) ContainerInspect(ctx context.Context, name string, size bo
}
shortCID := stringid.TruncateID(ctr.ID)
for _, ep := range ctr.NetworkSettings.Networks {
ep.Aliases = sliceutil.Dedup(append(ep.Aliases, shortCID, ctr.Config.Hostname))
for nwName, ep := range ctr.NetworkSettings.Networks {
if containertypes.NetworkMode(nwName).IsUserDefined() {
ep.Aliases = sliceutil.Dedup(append(ep.Aliases, shortCID, ctr.Config.Hostname))
}
}
return ctr, nil

View File

@@ -33,6 +33,8 @@ type Settings struct {
type EndpointSettings struct {
*networktypes.EndpointSettings
IPAMOperational bool
// MACOperational is false if EndpointSettings.MacAddress is a user-configured value.
MACOperational bool
}
// AttachmentStore stores the load balancer IP address for a network id.

View File

@@ -2,6 +2,7 @@ package daemon // import "github.com/docker/docker/daemon"
import (
"context"
"fmt"
"strings"
"github.com/containerd/log"
@@ -127,9 +128,9 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) (retErr error) {
return err
}
ep, err := nw.EndpointByID(epConfig.EndpointID)
if err != nil {
return err
ep := sb.GetEndpoint(epConfig.EndpointID)
if ep == nil {
return fmt.Errorf("no endpoint attached to network %s found", nw.Name())
}
oldDNSNames := make([]string, len(epConfig.DNSNames))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -52,18 +52,6 @@ info:
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.25 of the API, which was introduced with Docker 1.13. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:

View File

@@ -52,19 +52,6 @@ info:
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.26 of the API, which was introduced with Docker 1.13.1. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
1.13.0 | [1.25](https://docs.docker.com/engine/api/v1.25/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-25-api-changes)
1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:

View File

@@ -52,20 +52,6 @@ info:
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.27 of the API, which was introduced with Docker 17.03.1. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
1.13.1 & 17.03.0 | [1.26](https://docs.docker.com/engine/api/v1.26/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-26-api-changes)
1.13.0 | [1.25](https://docs.docker.com/engine/api/v1.25/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-25-api-changes)
1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:

View File

@@ -52,21 +52,6 @@ info:
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.28 of the API, which was introduced with Docker 17.04. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
17.03.1 | [1.27](https://docs.docker.com/engine/api/v1.27/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-27-api-changes)
1.13.1 & 17.03.0 | [1.26](https://docs.docker.com/engine/api/v1.26/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-26-api-changes)
1.13.0 | [1.25](https://docs.docker.com/engine/api/v1.25/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-25-api-changes)
1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:

View File

@@ -52,22 +52,6 @@ info:
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.29 of the API, which was introduced with Docker 17.05. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
17.04.x | [1.28](https://docs.docker.com/engine/api/v1.28/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-28-api-changes)
17.03.1 | [1.27](https://docs.docker.com/engine/api/v1.27/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-27-api-changes)
1.13.1 & 17.03.0 | [1.26](https://docs.docker.com/engine/api/v1.26/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-26-api-changes)
1.13.0 | [1.25](https://docs.docker.com/engine/api/v1.25/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-25-api-changes)
1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:

View File

@@ -52,23 +52,6 @@ info:
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.30 of the API, which was introduced with Docker 17.06. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
17.05.x | [1.29](https://docs.docker.com/engine/api/v1.29/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-29-api-changes)
17.04.x | [1.28](https://docs.docker.com/engine/api/v1.28/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-28-api-changes)
17.03.1 | [1.27](https://docs.docker.com/engine/api/v1.27/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-27-api-changes)
1.13.1 & 17.03.0 | [1.26](https://docs.docker.com/engine/api/v1.26/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-26-api-changes)
1.13.0 | [1.25](https://docs.docker.com/engine/api/v1.25/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-25-api-changes)
1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:

View File

@@ -52,24 +52,6 @@ info:
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.31 of the API. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
17.06.x | [1.30](https://docs.docker.com/engine/api/v1.30/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-30-api-changes)
17.05.x | [1.29](https://docs.docker.com/engine/api/v1.29/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-29-api-changes)
17.04.x | [1.28](https://docs.docker.com/engine/api/v1.28/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-28-api-changes)
17.03.1 | [1.27](https://docs.docker.com/engine/api/v1.27/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-27-api-changes)
1.13.1 & 17.03.0 | [1.26](https://docs.docker.com/engine/api/v1.26/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-26-api-changes)
1.13.0 | [1.25](https://docs.docker.com/engine/api/v1.25/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-25-api-changes)
1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:

View File

@@ -52,25 +52,6 @@ info:
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.32 of the API. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
17.07.x | [1.31](https://docs.docker.com/engine/api/v1.31/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-31-api-changes)
17.06.x | [1.30](https://docs.docker.com/engine/api/v1.30/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-30-api-changes)
17.05.x | [1.29](https://docs.docker.com/engine/api/v1.29/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-29-api-changes)
17.04.x | [1.28](https://docs.docker.com/engine/api/v1.28/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-28-api-changes)
17.03.1 | [1.27](https://docs.docker.com/engine/api/v1.27/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-27-api-changes)
1.13.1 & 17.03.0 | [1.26](https://docs.docker.com/engine/api/v1.26/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-26-api-changes)
1.13.0 | [1.25](https://docs.docker.com/engine/api/v1.25/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-25-api-changes)
1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:

View File

@@ -52,26 +52,6 @@ info:
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.33 of the API. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
17.09.x | [1.31](https://docs.docker.com/engine/api/v1.32/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-32-api-changes)
17.07.x | [1.31](https://docs.docker.com/engine/api/v1.31/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-31-api-changes)
17.06.x | [1.30](https://docs.docker.com/engine/api/v1.30/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-30-api-changes)
17.05.x | [1.29](https://docs.docker.com/engine/api/v1.29/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-29-api-changes)
17.04.x | [1.28](https://docs.docker.com/engine/api/v1.28/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-28-api-changes)
17.03.1 | [1.27](https://docs.docker.com/engine/api/v1.27/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-27-api-changes)
1.13.1 & 17.03.0 | [1.26](https://docs.docker.com/engine/api/v1.26/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-26-api-changes)
1.13.0 | [1.25](https://docs.docker.com/engine/api/v1.25/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-25-api-changes)
1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:

View File

@@ -54,27 +54,6 @@ info:
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.34 of the API. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
17.10.x | [1.33](https://docs.docker.com/engine/api/v1.33/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-33-api-changes)
17.09.x | [1.32](https://docs.docker.com/engine/api/v1.32/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-32-api-changes)
17.07.x | [1.31](https://docs.docker.com/engine/api/v1.31/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-31-api-changes)
17.06.x | [1.30](https://docs.docker.com/engine/api/v1.30/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-30-api-changes)
17.05.x | [1.29](https://docs.docker.com/engine/api/v1.29/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-29-api-changes)
17.04.x | [1.28](https://docs.docker.com/engine/api/v1.28/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-28-api-changes)
17.03.1 | [1.27](https://docs.docker.com/engine/api/v1.27/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-27-api-changes)
1.13.1 & 17.03.0 | [1.26](https://docs.docker.com/engine/api/v1.26/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-26-api-changes)
1.13.0 | [1.25](https://docs.docker.com/engine/api/v1.25/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-25-api-changes)
1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:

View File

@@ -29,7 +29,7 @@ import (
type imageDescriptor struct {
refs []reference.NamedTagged
layers []digest.Digest
layers []layer.DiffID
image *image.Image
layerRef layer.Layer
}
@@ -210,7 +210,9 @@ func (s *saveSession) save(outStream io.Writer) error {
foreign = make([]ocispec.Descriptor, 0, len(foreignSrcs))
)
for _, desc := range foreignSrcs {
// Layers in manifest must follow the actual layer order from config.
for _, l := range imageDescr.layers {
desc := foreignSrcs[l]
foreign = append(foreign, ocispec.Descriptor{
MediaType: desc.MediaType,
Digest: desc.Digest,
@@ -263,7 +265,7 @@ func (s *saveSession) save(outStream io.Writer) error {
if _, ok := reposLegacy[familiarName]; !ok {
reposLegacy[familiarName] = make(map[string]string)
}
reposLegacy[familiarName][ref.Tag()] = imageDescr.layers[len(imageDescr.layers)-1].Encoded()
reposLegacy[familiarName][ref.Tag()] = digest.Digest(imageDescr.layers[len(imageDescr.layers)-1]).Encoded()
repoTags = append(repoTags, reference.FamiliarString(ref))
manifestDescriptors = append(manifestDescriptors, ocispec.Descriptor{
@@ -281,7 +283,8 @@ func (s *saveSession) save(outStream io.Writer) error {
for _, l := range imageDescr.layers {
// IMPORTANT: We use path, not filepath here to ensure the layers
// in the manifest use Unix-style forward-slashes.
layers = append(layers, path.Join(ocispec.ImageBlobsDir, l.Algorithm().String(), l.Encoded()))
lDgst := digest.Digest(l)
layers = append(layers, path.Join(ocispec.ImageBlobsDir, lDgst.Algorithm().String(), lDgst.Encoded()))
}
manifest = append(manifest, manifestItem{
@@ -380,7 +383,7 @@ func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]distribution.Desc
}
var parent digest.Digest
var layers []digest.Digest
var layers []layer.DiffID
var foreignSrcs map[layer.DiffID]distribution.Descriptor
for i, diffID := range img.RootFS.DiffIDs {
v1ImgCreated := time.Unix(0, 0)
@@ -410,7 +413,7 @@ func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]distribution.Desc
return nil, err
}
layers = append(layers, digest.Digest(diffID))
layers = append(layers, diffID)
parent = v1ID
if src.Digest != "" {
if foreignSrcs == nil {

View File

@@ -1287,7 +1287,7 @@ func (s *DockerAPISuite) TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRoot
// Attempt to extract to a symlink in the volume which points to a
// directory outside the volume. This should cause an error because the
// rootfs is read-only.
apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.20"))
apiClient, err := client.NewClientWithOpts(client.FromEnv)
assert.NilError(c, err)
err = apiClient.CopyToContainer(testutil.GetContext(c), cID, "/vol2/symlinkToAbsDir", nil, types.CopyToContainerOptions{})

View File

@@ -159,6 +159,11 @@ func (s *DockerAPISuite) TestInspectAPIBridgeNetworkSettings120(c *testing.T) {
assert.Assert(c, len(settings.IPAddress) != 0)
}
// Inspect for API v1.21 and up; see
//
// - https://github.com/moby/moby/issues/17131
// - https://github.com/moby/moby/issues/17139
// - https://github.com/moby/moby/issues/17173
func (s *DockerAPISuite) TestInspectAPIBridgeNetworkSettings121(c *testing.T) {
// Windows doesn't have any bridge network settings
testRequires(c, DaemonIsLinux)
@@ -166,7 +171,7 @@ func (s *DockerAPISuite) TestInspectAPIBridgeNetworkSettings121(c *testing.T) {
containerID := strings.TrimSpace(out)
cli.WaitRun(c, containerID)
body := getInspectBody(c, "v1.21", containerID)
body := getInspectBody(c, "", containerID)
var inspectJSON types.ContainerJSON
err := json.Unmarshal(body, &inspectJSON)

View File

@@ -1022,15 +1022,16 @@ func (s *DockerCLINetworkSuite) TestInspectAPIMultipleNetworks(c *testing.T) {
versionedIP := inspect120.NetworkSettings.IPAddress
body = getInspectBody(c, "v1.21", id)
var inspect121 types.ContainerJSON
err = json.Unmarshal(body, &inspect121)
// Current API version (API v1.21 and up)
body = getInspectBody(c, "", id)
var inspectCurrent types.ContainerJSON
err = json.Unmarshal(body, &inspectCurrent)
assert.NilError(c, err)
assert.Equal(c, len(inspect121.NetworkSettings.Networks), 3)
assert.Equal(c, len(inspectCurrent.NetworkSettings.Networks), 3)
bridge := inspect121.NetworkSettings.Networks["bridge"]
bridge := inspectCurrent.NetworkSettings.Networks["bridge"]
assert.Equal(c, bridge.IPAddress, versionedIP)
assert.Equal(c, bridge.IPAddress, inspect121.NetworkSettings.IPAddress)
assert.Equal(c, bridge.IPAddress, inspectCurrent.NetworkSettings.IPAddress)
}
func connectContainerToNetworks(c *testing.T, d *daemon.Daemon, cName string, nws []string) {

View File

@@ -2,10 +2,12 @@ package container // import "github.com/docker/docker/integration/container"
import (
"encoding/json"
"runtime"
"strings"
"testing"
"time"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/testutil/request"
@@ -68,3 +70,33 @@ func TestInspectAnnotations(t *testing.T) {
assert.NilError(t, err)
assert.Check(t, is.DeepEqual(inspect.HostConfig.Annotations, annotations))
}
// TestNetworkAliasesAreEmpty verifies that network-scoped aliases are not set
// for non-custom networks (network-scoped aliases are only supported for
// custom networks, except for the "Default Switch" network on Windows).
func TestNetworkAliasesAreEmpty(t *testing.T) {
ctx := setupTest(t)
apiClient := request.NewAPIClient(t)
netModes := []string{"host", "bridge", "none"}
if runtime.GOOS == "windows" {
netModes = []string{"nat", "none"}
}
for _, nwMode := range netModes {
t.Run(nwMode, func(t *testing.T) {
ctr := container.Create(ctx, t, apiClient,
container.WithName("ctr-"+nwMode),
container.WithImage("busybox:latest"),
container.WithNetworkMode(nwMode))
defer apiClient.ContainerRemove(ctx, ctr, containertypes.RemoveOptions{
Force: true,
})
inspect := container.Inspect(ctx, t, apiClient, ctr)
netAliases := inspect.NetworkSettings.Networks[nwMode].Aliases
assert.Check(t, is.Nil(netAliases))
})
}
}

View File

@@ -192,3 +192,25 @@ func TestRenameContainerWithLinkedContainer(t *testing.T) {
assert.NilError(t, err)
assert.Check(t, is.Equal(db1ID, inspect.ID))
}
// Regression test for https://github.com/moby/moby/issues/47186
func TestRenameContainerTwice(t *testing.T) {
ctx := setupTest(t)
apiClient := testEnv.APIClient()
ctrName := "c0"
container.Run(ctx, t, apiClient, container.WithName("c0"))
defer func() {
container.Remove(ctx, t, apiClient, ctrName, containertypes.RemoveOptions{
Force: true,
})
}()
err := apiClient.ContainerRename(ctx, "c0", "c1")
assert.NilError(t, err)
ctrName = "c1"
err = apiClient.ContainerRename(ctx, "c1", "c2")
assert.NilError(t, err)
ctrName = "c2"
}

View File

@@ -289,3 +289,40 @@ func TestMacAddressIsAppliedToMainNetworkWithShortID(t *testing.T) {
c := container.Inspect(ctx, t, apiClient, cid)
assert.Equal(t, c.NetworkSettings.Networks["testnet"].MacAddress, "02:42:08:26:a9:55")
}
func TestStaticIPOutsideSubpool(t *testing.T) {
skip.If(t, testEnv.IsRemoteDaemon)
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
ctx := testutil.StartSpan(baseContext, t)
d := daemon.New(t)
d.StartWithBusybox(ctx, t)
defer d.Stop(t)
apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("1.43"))
assert.NilError(t, err)
const netname = "subnet-range"
n := net.CreateNoError(ctx, t, apiClient, netname, net.WithIPAMRange("10.42.0.0/16", "10.42.128.0/24", "10.42.0.1"))
defer net.RemoveNoError(ctx, t, apiClient, n)
cID := container.Run(ctx, t, apiClient,
container.WithImage("busybox:latest"),
container.WithCmd("sh", "-c", `ip -4 -oneline addr show eth0`),
container.WithNetworkMode(netname),
container.WithIPv4(netname, "10.42.1.3"),
)
poll.WaitOn(t, container.IsStopped(ctx, apiClient, cID), poll.WithDelay(100*time.Millisecond))
out, err := apiClient.ContainerLogs(ctx, cID, containertypes.LogsOptions{ShowStdout: true})
assert.NilError(t, err)
defer out.Close()
var b bytes.Buffer
_, err = io.Copy(&b, out)
assert.NilError(t, err)
assert.Check(t, is.Contains(b.String(), "inet 10.42.1.3/16"))
}

View File

@@ -73,6 +73,11 @@ func WithOption(key, value string) func(*types.NetworkCreate) {
// WithIPAM adds an IPAM with the specified Subnet and Gateway to the network
func WithIPAM(subnet, gateway string) func(*types.NetworkCreate) {
return WithIPAMRange(subnet, "", gateway)
}
// WithIPAM adds an IPAM with the specified Subnet, IPRange and Gateway to the network
func WithIPAMRange(subnet, iprange, gateway string) func(*types.NetworkCreate) {
return func(n *types.NetworkCreate) {
if n.IPAM == nil {
n.IPAM = &network.IPAM{}
@@ -80,6 +85,7 @@ func WithIPAM(subnet, gateway string) func(*types.NetworkCreate) {
n.IPAM.Config = append(n.IPAM.Config, network.IPAMConfig{
Subnet: subnet,
IPRange: iprange,
Gateway: gateway,
AuxAddress: map[string]string{},
})

View File

@@ -0,0 +1,79 @@
package networking
import (
"testing"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/integration/internal/network"
"github.com/docker/docker/testutil/daemon"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/skip"
)
// TestMACAddrOnRestart is a regression test for https://github.com/moby/moby/issues/47146
// - Start a container, let it use a generated MAC address.
// - Stop that container.
// - Start a second container, it'll also use a generated MAC address.
// (It's likely to recycle the first container's MAC address.)
// - Restart the first container.
// (The bug was that it kept its original MAC address, now already in-use.)
// - Check that the two containers have different MAC addresses.
func TestMACAddrOnRestart(t *testing.T) {
skip.If(t, testEnv.DaemonInfo.OSType == "windows")
ctx := setupTest(t)
d := daemon.New(t)
d.StartWithBusybox(ctx, t)
defer d.Stop(t)
c := d.NewClientT(t)
defer c.Close()
const netName = "testmacaddrs"
network.CreateNoError(ctx, t, c, netName,
network.WithDriver("bridge"),
network.WithOption("com.docker.network.bridge.name", netName))
defer network.RemoveNoError(ctx, t, c, netName)
const ctr1Name = "ctr1"
id1 := container.Run(ctx, t, c,
container.WithName(ctr1Name),
container.WithImage("busybox:latest"),
container.WithCmd("top"),
container.WithNetworkMode(netName))
defer c.ContainerRemove(ctx, id1, containertypes.RemoveOptions{
Force: true,
})
err := c.ContainerStop(ctx, ctr1Name, containertypes.StopOptions{})
assert.Assert(t, is.Nil(err))
// Start a second container, giving the daemon a chance to recycle the first container's
// IP and MAC addresses.
const ctr2Name = "ctr2"
id2 := container.Run(ctx, t, c,
container.WithName(ctr2Name),
container.WithImage("busybox:latest"),
container.WithCmd("top"),
container.WithNetworkMode(netName))
defer c.ContainerRemove(ctx, id2, containertypes.RemoveOptions{
Force: true,
})
// Restart the first container.
err = c.ContainerStart(ctx, ctr1Name, containertypes.StartOptions{})
assert.Assert(t, is.Nil(err))
// Check that the containers ended up with different MAC addresses.
ctr1Inspect := container.Inspect(ctx, t, c, ctr1Name)
ctr1MAC := ctr1Inspect.NetworkSettings.Networks[netName].MacAddress
ctr2Inspect := container.Inspect(ctx, t, c, ctr2Name)
ctr2MAC := ctr2Inspect.NetworkSettings.Networks[netName].MacAddress
assert.Check(t, ctr1MAC != ctr2MAC,
"expected containers to have different MAC addresses; got %q for both", ctr1MAC)
}

View File

@@ -623,7 +623,7 @@ func (ep *Endpoint) addServiceInfoToCluster(sb *Sandbox) error {
// In case the deleteServiceInfoToCluster arrives first, this one is happening after the endpoint is
// removed from the list, in this situation the delete will bail out not finding any data to cleanup
// and the add will bail out not finding the endpoint on the sandbox.
if err := sb.getEndpoint(ep.ID()); err == nil {
if err := sb.GetEndpoint(ep.ID()); err == nil {
log.G(context.TODO()).Warnf("addServiceInfoToCluster suppressing service resolution ep is not anymore in the sandbox %s", ep.ID())
return nil
}
@@ -692,7 +692,7 @@ func (ep *Endpoint) deleteServiceInfoFromCluster(sb *Sandbox, fullRemove bool, m
// get caught in disableServceInNetworkDB, but we check here to make the
// nature of the condition more clear.
// See comment in addServiceInfoToCluster()
if err := sb.getEndpoint(ep.ID()); err == nil {
if err := sb.GetEndpoint(ep.ID()); err == nil {
log.G(context.TODO()).Warnf("deleteServiceInfoFromCluster suppressing service resolution ep is not anymore in the sandbox %s", ep.ID())
return nil
}

View File

@@ -194,7 +194,7 @@ func (ep *Endpoint) Info() EndpointInfo {
return ep
}
return sb.getEndpoint(ep.ID())
return sb.GetEndpoint(ep.ID())
}
// Iface returns information about the interface which was assigned to

View File

@@ -83,7 +83,7 @@ type IpamConf struct {
// PreferredPool is the master address pool for containers and network interfaces.
PreferredPool string
// SubPool is a subset of the master pool. If specified,
// this becomes the container pool.
// this becomes the container pool for automatic address allocations.
SubPool string
// Gateway is the preferred Network Gateway address (optional).
Gateway string
@@ -100,7 +100,7 @@ func (c *IpamConf) Validate() error {
return nil
}
// Contains checks whether the ipamSubnet contains [addr].
// Contains checks whether the ipam master address pool contains [addr].
func (c *IpamConf) Contains(addr net.IP) bool {
if c == nil {
return false
@@ -110,9 +110,6 @@ func (c *IpamConf) Contains(addr net.IP) bool {
}
_, allowedRange, _ := net.ParseCIDR(c.PreferredPool)
if c.SubPool != "" {
_, allowedRange, _ = net.ParseCIDR(c.SubPool)
}
return allowedRange.Contains(addr)
}
@@ -1279,8 +1276,8 @@ func (n *Network) EndpointByName(name string) (*Endpoint, error) {
return e, nil
}
// EndpointByID returns the Endpoint which has the passed id. If not found,
// the error ErrNoSuchEndpoint is returned.
// EndpointByID should *never* be called as it's going to create a 2nd instance of an Endpoint. The first one lives in
// the Sandbox the endpoint is attached to. Instead, the endpoint should be retrieved by calling [Sandbox.Endpoints()].
func (n *Network) EndpointByID(id string) (*Endpoint, error) {
if id == "" {
return nil, ErrInvalidID(id)

View File

@@ -334,7 +334,7 @@ func (sb *Sandbox) removeEndpointRaw(ep *Endpoint) {
}
}
func (sb *Sandbox) getEndpoint(id string) *Endpoint {
func (sb *Sandbox) GetEndpoint(id string) *Endpoint {
sb.mu.Lock()
defer sb.mu.Unlock()
@@ -587,7 +587,7 @@ func (sb *Sandbox) DisableService() (err error) {
}
func (sb *Sandbox) clearNetworkResources(origEp *Endpoint) error {
ep := sb.getEndpoint(origEp.id)
ep := sb.GetEndpoint(origEp.id)
if ep == nil {
return fmt.Errorf("could not find the sandbox endpoint data for endpoint %s",
origEp.id)

View File

@@ -57,7 +57,7 @@ func (n *Network) findLBEndpointSandbox() (*Endpoint, *Sandbox, error) {
if !ok {
return nil, nil, fmt.Errorf("Unable to get sandbox for %s(%s) in for %s", ep.Name(), ep.ID(), n.ID())
}
sep := sb.getEndpoint(ep.ID())
sep := sb.GetEndpoint(ep.ID())
if sep == nil {
return nil, nil, fmt.Errorf("Load balancing endpoint %s(%s) removed from %s", ep.Name(), ep.ID(), n.ID())
}

18
pkg/system/xattrs.go Normal file
View File

@@ -0,0 +1,18 @@
package system // import "github.com/docker/docker/pkg/system"
type XattrError struct {
Op string
Attr string
Path string
Err error
}
func (e *XattrError) Error() string { return e.Op + " " + e.Attr + " " + e.Path + ": " + e.Err.Error() }
func (e *XattrError) Unwrap() error { return e.Err }
// Timeout reports whether this error represents a timeout.
func (e *XattrError) Timeout() bool {
t, ok := e.Err.(interface{ Timeout() bool })
return ok && t.Timeout()
}

View File

@@ -1,8 +1,6 @@
package system // import "github.com/docker/docker/pkg/system"
import (
"io/fs"
"golang.org/x/sys/unix"
)
@@ -10,8 +8,8 @@ import (
// and associated with the given path in the file system.
// It will returns a nil slice and nil error if the xattr is not set.
func Lgetxattr(path string, attr string) ([]byte, error) {
pathErr := func(err error) ([]byte, error) {
return nil, &fs.PathError{Op: "lgetxattr", Path: path, Err: err}
sysErr := func(err error) ([]byte, error) {
return nil, &XattrError{Op: "lgetxattr", Attr: attr, Path: path, Err: err}
}
// Start with a 128 length byte array
@@ -22,7 +20,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) {
// Buffer too small, use zero-sized buffer to get the actual size
sz, errno = unix.Lgetxattr(path, attr, []byte{})
if errno != nil {
return pathErr(errno)
return sysErr(errno)
}
dest = make([]byte, sz)
sz, errno = unix.Lgetxattr(path, attr, dest)
@@ -32,7 +30,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) {
case errno == unix.ENODATA:
return nil, nil
case errno != nil:
return pathErr(errno)
return sysErr(errno)
}
return dest[:sz], nil
@@ -43,7 +41,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) {
func Lsetxattr(path string, attr string, data []byte, flags int) error {
err := unix.Lsetxattr(path, attr, data, flags)
if err != nil {
return &fs.PathError{Op: "lsetxattr", Path: path, Err: err}
return &XattrError{Op: "lsetxattr", Attr: attr, Path: path, Err: err}
}
return nil
}

View File

@@ -3,6 +3,7 @@
package local // import "github.com/docker/docker/volume/local"
import (
"net"
"os"
"path/filepath"
"strconv"
@@ -246,3 +247,84 @@ func TestVolCreateValidation(t *testing.T) {
})
}
}
func TestVolMountOpts(t *testing.T) {
tests := []struct {
name string
opts optsConfig
expectedErr string
expectedDevice, expectedOpts string
}{
{
name: "cifs url with space",
opts: optsConfig{
MountType: "cifs",
MountDevice: "//1.2.3.4/Program Files",
},
expectedDevice: "//1.2.3.4/Program Files",
expectedOpts: "",
},
{
name: "cifs resolve addr",
opts: optsConfig{
MountType: "cifs",
MountDevice: "//example.com/Program Files",
MountOpts: "addr=example.com",
},
expectedDevice: "//example.com/Program Files",
expectedOpts: "addr=1.2.3.4",
},
{
name: "cifs resolve device",
opts: optsConfig{
MountType: "cifs",
MountDevice: "//example.com/Program Files",
},
expectedDevice: "//1.2.3.4/Program Files",
},
{
name: "nfs dont resolve device",
opts: optsConfig{
MountType: "nfs",
MountDevice: "//example.com/Program Files",
},
expectedDevice: "//example.com/Program Files",
},
{
name: "nfs resolve addr",
opts: optsConfig{
MountType: "nfs",
MountDevice: "//example.com/Program Files",
MountOpts: "addr=example.com",
},
expectedDevice: "//example.com/Program Files",
expectedOpts: "addr=1.2.3.4",
},
}
ip1234 := net.ParseIP("1.2.3.4")
resolveIP := func(network, addr string) (*net.IPAddr, error) {
switch addr {
case "example.com":
return &net.IPAddr{IP: ip1234}, nil
}
return nil, &net.DNSError{Err: "no such host", Name: addr, IsNotFound: true}
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
dev, opts, err := getMountOptions(&tc.opts, resolveIP)
if tc.expectedErr != "" {
assert.Check(t, is.ErrorContains(err, tc.expectedErr))
} else {
assert.Check(t, err)
}
assert.Check(t, is.Equal(dev, tc.expectedDevice))
assert.Check(t, is.Equal(opts, tc.expectedOpts))
})
}
}

View File

@@ -118,37 +118,56 @@ func (v *localVolume) needsMount() bool {
return false
}
func (v *localVolume) mount() error {
if v.opts.MountDevice == "" {
return fmt.Errorf("missing device in volume options")
func getMountOptions(opts *optsConfig, resolveIP func(string, string) (*net.IPAddr, error)) (mountDevice string, mountOpts string, _ error) {
if opts.MountDevice == "" {
return "", "", fmt.Errorf("missing device in volume options")
}
mountOpts := v.opts.MountOpts
mountDevice := v.opts.MountDevice
mountOpts = opts.MountOpts
mountDevice = opts.MountDevice
switch v.opts.MountType {
case "nfs":
if addrValue := getAddress(v.opts.MountOpts); addrValue != "" && net.ParseIP(addrValue).To4() == nil {
ipAddr, err := net.ResolveIPAddr("ip", addrValue)
switch opts.MountType {
case "nfs", "cifs":
if addrValue := getAddress(opts.MountOpts); addrValue != "" && net.ParseIP(addrValue).To4() == nil {
ipAddr, err := resolveIP("ip", addrValue)
if err != nil {
return errors.Wrapf(err, "error resolving passed in network volume address")
return "", "", errors.Wrap(err, "error resolving passed in network volume address")
}
mountOpts = strings.Replace(mountOpts, "addr="+addrValue, "addr="+ipAddr.String(), 1)
break
}
case "cifs":
deviceURL, err := url.Parse(v.opts.MountDevice)
if opts.MountType != "cifs" {
break
}
deviceURL, err := url.Parse(mountDevice)
if err != nil {
return errors.Wrapf(err, "error parsing mount device url")
return "", "", errors.Wrap(err, "error parsing mount device url")
}
if deviceURL.Host != "" && net.ParseIP(deviceURL.Host) == nil {
ipAddr, err := net.ResolveIPAddr("ip", deviceURL.Host)
ipAddr, err := resolveIP("ip", deviceURL.Host)
if err != nil {
return errors.Wrapf(err, "error resolving passed in network volume address")
return "", "", errors.Wrap(err, "error resolving passed in network volume address")
}
deviceURL.Host = ipAddr.String()
mountDevice = deviceURL.String()
dev, err := url.QueryUnescape(deviceURL.String())
if err != nil {
return "", "", fmt.Errorf("failed to unescape device URL: %q", deviceURL)
}
mountDevice = dev
}
}
return mountDevice, mountOpts, nil
}
func (v *localVolume) mount() error {
mountDevice, mountOpts, err := getMountOptions(v.opts, net.ResolveIPAddr)
if err != nil {
return err
}
if err := mount.Mount(mountDevice, v.path, v.opts.MountType, mountOpts); err != nil {
if password := getPassword(v.opts.MountOpts); password != "" {
err = errors.New(strings.Replace(err.Error(), "password="+password, "password=********", 1))