فهرست منبع

Merge pull request #43206 from thaJeztah/having_such_a_good_time_im_having_a_ball

API: add "signal" parameter to container stop and restart endpoints
Sebastiaan van Stijn 3 سال پیش
والد
کامیت
1a0c15abbb

+ 2 - 2
api/server/router/container/backend.go

@@ -37,10 +37,10 @@ type stateBackend interface {
 	ContainerPause(name string) error
 	ContainerPause(name string) error
 	ContainerRename(oldName, newName string) error
 	ContainerRename(oldName, newName string) error
 	ContainerResize(name string, height, width int) error
 	ContainerResize(name string, height, width int) error
-	ContainerRestart(name string, seconds *int) error
+	ContainerRestart(ctx context.Context, name string, options container.StopOptions) error
 	ContainerRm(name string, config *types.ContainerRmConfig) error
 	ContainerRm(name string, config *types.ContainerRmConfig) error
 	ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
 	ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
-	ContainerStop(name string, seconds *int) error
+	ContainerStop(ctx context.Context, name string, options container.StopOptions) error
 	ContainerUnpause(name string) error
 	ContainerUnpause(name string) error
 	ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error)
 	ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error)
 	ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
 	ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)

+ 29 - 8
api/server/router/container/container_routes.go

@@ -221,20 +221,31 @@ func (s *containerRouter) postContainersStop(ctx context.Context, w http.Respons
 		return err
 		return err
 	}
 	}
 
 
-	var seconds *int
+	var (
+		options container.StopOptions
+		version = httputils.VersionFromContext(ctx)
+	)
+	if versions.GreaterThanOrEqualTo(version, "1.42") {
+		if sig := r.Form.Get("signal"); sig != "" {
+			if _, err := signal.ParseSignal(sig); err != nil {
+				return errdefs.InvalidParameter(err)
+			}
+			options.Signal = sig
+		}
+	}
 	if tmpSeconds := r.Form.Get("t"); tmpSeconds != "" {
 	if tmpSeconds := r.Form.Get("t"); tmpSeconds != "" {
 		valSeconds, err := strconv.Atoi(tmpSeconds)
 		valSeconds, err := strconv.Atoi(tmpSeconds)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		seconds = &valSeconds
+		options.Timeout = &valSeconds
 	}
 	}
 
 
-	if err := s.backend.ContainerStop(vars["name"], seconds); err != nil {
+	if err := s.backend.ContainerStop(ctx, vars["name"], options); err != nil {
 		return err
 		return err
 	}
 	}
-	w.WriteHeader(http.StatusNoContent)
 
 
+	w.WriteHeader(http.StatusNoContent)
 	return nil
 	return nil
 }
 }
 
 
@@ -278,21 +289,31 @@ func (s *containerRouter) postContainersRestart(ctx context.Context, w http.Resp
 		return err
 		return err
 	}
 	}
 
 
-	var seconds *int
+	var (
+		options container.StopOptions
+		version = httputils.VersionFromContext(ctx)
+	)
+	if versions.GreaterThanOrEqualTo(version, "1.42") {
+		if sig := r.Form.Get("signal"); sig != "" {
+			if _, err := signal.ParseSignal(sig); err != nil {
+				return errdefs.InvalidParameter(err)
+			}
+			options.Signal = sig
+		}
+	}
 	if tmpSeconds := r.Form.Get("t"); tmpSeconds != "" {
 	if tmpSeconds := r.Form.Get("t"); tmpSeconds != "" {
 		valSeconds, err := strconv.Atoi(tmpSeconds)
 		valSeconds, err := strconv.Atoi(tmpSeconds)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		seconds = &valSeconds
+		options.Timeout = &valSeconds
 	}
 	}
 
 
-	if err := s.backend.ContainerRestart(vars["name"], seconds); err != nil {
+	if err := s.backend.ContainerRestart(ctx, vars["name"], options); err != nil {
 		return err
 		return err
 	}
 	}
 
 
 	w.WriteHeader(http.StatusNoContent)
 	w.WriteHeader(http.StatusNoContent)
-
 	return nil
 	return nil
 }
 }
 
 

+ 12 - 1
api/swagger.yaml

@@ -6869,6 +6869,11 @@ paths:
           required: true
           required: true
           description: "ID or name of the container"
           description: "ID or name of the container"
           type: "string"
           type: "string"
+        - name: "signal"
+          in: "query"
+          description: |
+            Signal to send to the container as an integer or string (e.g. `SIGINT`).
+          type: "string"
         - name: "t"
         - name: "t"
           in: "query"
           in: "query"
           description: "Number of seconds to wait before killing the container"
           description: "Number of seconds to wait before killing the container"
@@ -6898,6 +6903,11 @@ paths:
           required: true
           required: true
           description: "ID or name of the container"
           description: "ID or name of the container"
           type: "string"
           type: "string"
+        - name: "signal"
+          in: "query"
+          description: |
+            Signal to send to the container as an integer or string (e.g. `SIGINT`).
+          type: "string"
         - name: "t"
         - name: "t"
           in: "query"
           in: "query"
           description: "Number of seconds to wait before killing the container"
           description: "Number of seconds to wait before killing the container"
@@ -6939,7 +6949,8 @@ paths:
           type: "string"
           type: "string"
         - name: "signal"
         - name: "signal"
           in: "query"
           in: "query"
-          description: "Signal to send to the container as an integer or string (e.g. `SIGINT`)"
+          description: |
+            Signal to send to the container as an integer or string (e.g. `SIGINT`).
           type: "string"
           type: "string"
           default: "SIGKILL"
           default: "SIGKILL"
       tags: ["Container"]
       tags: ["Container"]

+ 18 - 0
api/types/container/config.go

@@ -13,6 +13,24 @@ import (
 // Docker interprets it as 3 nanoseconds.
 // Docker interprets it as 3 nanoseconds.
 const MinimumDuration = 1 * time.Millisecond
 const MinimumDuration = 1 * time.Millisecond
 
 
+// StopOptions holds the options to stop or restart a container.
+type StopOptions struct {
+	// Signal (optional) is the signal to send to the container to (gracefully)
+	// stop it before forcibly terminating the container with SIGKILL after the
+	// timeout expires. If not value is set, the default (SIGTERM) is used.
+	Signal string `json:",omitempty"`
+
+	// Timeout (optional) is the timeout (in seconds) to wait for the container
+	// to stop gracefully before forcibly terminating it with SIGKILL.
+	//
+	// - Use nil to use the default timeout (10 seconds).
+	// - Use '-1' to wait indefinitely.
+	// - Use '0' to not wait for the container to exit gracefully, and
+	//   immediately proceeds to forcibly terminating the container.
+	// - Other positive values are used as timeout (in seconds).
+	Timeout *int `json:",omitempty"`
+}
+
 // HealthConfig holds configuration settings for the HEALTHCHECK feature.
 // HealthConfig holds configuration settings for the HEALTHCHECK feature.
 type HealthConfig struct {
 type HealthConfig struct {
 	// Test is the test to perform to check that the container is healthy.
 	// Test is the test to perform to check that the container is healthy.

+ 0 - 12
api/types/time/duration_convert.go

@@ -1,12 +0,0 @@
-package time // import "github.com/docker/docker/api/types/time"
-
-import (
-	"strconv"
-	"time"
-)
-
-// DurationToSecondsString converts the specified duration to the number
-// seconds it represents, formatted as a string.
-func DurationToSecondsString(duration time.Duration) string {
-	return strconv.FormatFloat(duration.Seconds(), 'f', 0, 64)
-}

+ 0 - 26
api/types/time/duration_convert_test.go

@@ -1,26 +0,0 @@
-package time // import "github.com/docker/docker/api/types/time"
-
-import (
-	"testing"
-	"time"
-)
-
-func TestDurationToSecondsString(t *testing.T) {
-	cases := []struct {
-		in       time.Duration
-		expected string
-	}{
-		{0 * time.Second, "0"},
-		{1 * time.Second, "1"},
-		{1 * time.Minute, "60"},
-		{24 * time.Hour, "86400"},
-	}
-
-	for _, c := range cases {
-		s := DurationToSecondsString(c.in)
-		if s != c.expected {
-			t.Errorf("wrong value for input `%v`: expected `%s`, got `%s`", c.in, c.expected, s)
-			t.Fail()
-		}
-	}
-}

+ 9 - 5
client/container_restart.go

@@ -3,18 +3,22 @@ package client // import "github.com/docker/docker/client"
 import (
 import (
 	"context"
 	"context"
 	"net/url"
 	"net/url"
-	"time"
+	"strconv"
 
 
-	timetypes "github.com/docker/docker/api/types/time"
+	"github.com/docker/docker/api/types/container"
+	"github.com/docker/docker/api/types/versions"
 )
 )
 
 
 // ContainerRestart stops and starts a container again.
 // ContainerRestart stops and starts a container again.
 // It makes the daemon wait for the container to be up again for
 // It makes the daemon wait for the container to be up again for
 // a specific amount of time, given the timeout.
 // a specific amount of time, given the timeout.
-func (cli *Client) ContainerRestart(ctx context.Context, containerID string, timeout *time.Duration) error {
+func (cli *Client) ContainerRestart(ctx context.Context, containerID string, options container.StopOptions) error {
 	query := url.Values{}
 	query := url.Values{}
-	if timeout != nil {
-		query.Set("t", timetypes.DurationToSecondsString(*timeout))
+	if options.Timeout != nil {
+		query.Set("t", strconv.Itoa(*options.Timeout))
+	}
+	if options.Signal != "" && versions.GreaterThanOrEqualTo(cli.version, "1.42") {
+		query.Set("signal", options.Signal)
 	}
 	}
 	resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil)
 	resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil)
 	ensureReaderClosed(resp)
 	ensureReaderClosed(resp)

+ 13 - 6
client/container_restart_test.go

@@ -8,8 +8,8 @@ import (
 	"net/http"
 	"net/http"
 	"strings"
 	"strings"
 	"testing"
 	"testing"
-	"time"
 
 
+	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/errdefs"
 )
 )
 
 
@@ -17,20 +17,23 @@ func TestContainerRestartError(t *testing.T) {
 	client := &Client{
 	client := &Client{
 		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 	}
-	timeout := 0 * time.Second
-	err := client.ContainerRestart(context.Background(), "nothing", &timeout)
+	err := client.ContainerRestart(context.Background(), "nothing", container.StopOptions{})
 	if !errdefs.IsSystem(err) {
 	if !errdefs.IsSystem(err) {
 		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
 		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
 	}
 	}
 }
 }
 
 
 func TestContainerRestart(t *testing.T) {
 func TestContainerRestart(t *testing.T) {
-	expectedURL := "/containers/container_id/restart"
+	const expectedURL = "/v1.42/containers/container_id/restart"
 	client := &Client{
 	client := &Client{
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
 			}
 			}
+			s := req.URL.Query().Get("signal")
+			if s != "SIGKILL" {
+				return nil, fmt.Errorf("signal not set in URL query. Expected 'SIGKILL', got '%s'", s)
+			}
 			t := req.URL.Query().Get("t")
 			t := req.URL.Query().Get("t")
 			if t != "100" {
 			if t != "100" {
 				return nil, fmt.Errorf("t (timeout) not set in URL query properly. Expected '100', got %s", t)
 				return nil, fmt.Errorf("t (timeout) not set in URL query properly. Expected '100', got %s", t)
@@ -40,9 +43,13 @@ func TestContainerRestart(t *testing.T) {
 				Body:       io.NopCloser(bytes.NewReader([]byte(""))),
 				Body:       io.NopCloser(bytes.NewReader([]byte(""))),
 			}, nil
 			}, nil
 		}),
 		}),
+		version: "1.42",
 	}
 	}
-	timeout := 100 * time.Second
-	err := client.ContainerRestart(context.Background(), "container_id", &timeout)
+	timeout := 100
+	err := client.ContainerRestart(context.Background(), "container_id", container.StopOptions{
+		Signal:  "SIGKILL",
+		Timeout: &timeout,
+	})
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}

+ 9 - 5
client/container_stop.go

@@ -3,9 +3,10 @@ package client // import "github.com/docker/docker/client"
 import (
 import (
 	"context"
 	"context"
 	"net/url"
 	"net/url"
-	"time"
+	"strconv"
 
 
-	timetypes "github.com/docker/docker/api/types/time"
+	"github.com/docker/docker/api/types/container"
+	"github.com/docker/docker/api/types/versions"
 )
 )
 
 
 // ContainerStop stops a container. In case the container fails to stop
 // ContainerStop stops a container. In case the container fails to stop
@@ -15,10 +16,13 @@ import (
 // If the timeout is nil, the container's StopTimeout value is used, if set,
 // If the timeout is nil, the container's StopTimeout value is used, if set,
 // otherwise the engine default. A negative timeout value can be specified,
 // otherwise the engine default. A negative timeout value can be specified,
 // meaning no timeout, i.e. no forceful termination is performed.
 // meaning no timeout, i.e. no forceful termination is performed.
-func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout *time.Duration) error {
+func (cli *Client) ContainerStop(ctx context.Context, containerID string, options container.StopOptions) error {
 	query := url.Values{}
 	query := url.Values{}
-	if timeout != nil {
-		query.Set("t", timetypes.DurationToSecondsString(*timeout))
+	if options.Timeout != nil {
+		query.Set("t", strconv.Itoa(*options.Timeout))
+	}
+	if options.Signal != "" && versions.GreaterThanOrEqualTo(cli.version, "1.42") {
+		query.Set("signal", options.Signal)
 	}
 	}
 	resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil)
 	resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil)
 	ensureReaderClosed(resp)
 	ensureReaderClosed(resp)

+ 13 - 6
client/container_stop_test.go

@@ -8,8 +8,8 @@ import (
 	"net/http"
 	"net/http"
 	"strings"
 	"strings"
 	"testing"
 	"testing"
-	"time"
 
 
+	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/errdefs"
 )
 )
 
 
@@ -17,20 +17,23 @@ func TestContainerStopError(t *testing.T) {
 	client := &Client{
 	client := &Client{
 		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 	}
-	timeout := 0 * time.Second
-	err := client.ContainerStop(context.Background(), "nothing", &timeout)
+	err := client.ContainerStop(context.Background(), "nothing", container.StopOptions{})
 	if !errdefs.IsSystem(err) {
 	if !errdefs.IsSystem(err) {
 		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
 		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
 	}
 	}
 }
 }
 
 
 func TestContainerStop(t *testing.T) {
 func TestContainerStop(t *testing.T) {
-	expectedURL := "/containers/container_id/stop"
+	const expectedURL = "/v1.42/containers/container_id/stop"
 	client := &Client{
 	client := &Client{
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
 			}
 			}
+			s := req.URL.Query().Get("signal")
+			if s != "SIGKILL" {
+				return nil, fmt.Errorf("signal not set in URL query. Expected 'SIGKILL', got '%s'", s)
+			}
 			t := req.URL.Query().Get("t")
 			t := req.URL.Query().Get("t")
 			if t != "100" {
 			if t != "100" {
 				return nil, fmt.Errorf("t (timeout) not set in URL query properly. Expected '100', got %s", t)
 				return nil, fmt.Errorf("t (timeout) not set in URL query properly. Expected '100', got %s", t)
@@ -40,9 +43,13 @@ func TestContainerStop(t *testing.T) {
 				Body:       io.NopCloser(bytes.NewReader([]byte(""))),
 				Body:       io.NopCloser(bytes.NewReader([]byte(""))),
 			}, nil
 			}, nil
 		}),
 		}),
+		version: "1.42",
 	}
 	}
-	timeout := 100 * time.Second
-	err := client.ContainerStop(context.Background(), "container_id", &timeout)
+	timeout := 100
+	err := client.ContainerStop(context.Background(), "container_id", container.StopOptions{
+		Signal:  "SIGKILL",
+		Timeout: &timeout,
+	})
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}

+ 13 - 14
client/interface.go

@@ -5,17 +5,16 @@ import (
 	"io"
 	"io"
 	"net"
 	"net"
 	"net/http"
 	"net/http"
-	"time"
 
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
-	containertypes "github.com/docker/docker/api/types/container"
+	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/events"
 	"github.com/docker/docker/api/types/events"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/image"
 	"github.com/docker/docker/api/types/image"
-	networktypes "github.com/docker/docker/api/types/network"
+	"github.com/docker/docker/api/types/network"
 	"github.com/docker/docker/api/types/registry"
 	"github.com/docker/docker/api/types/registry"
 	"github.com/docker/docker/api/types/swarm"
 	"github.com/docker/docker/api/types/swarm"
-	volumetypes "github.com/docker/docker/api/types/volume"
+	"github.com/docker/docker/api/types/volume"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 )
 )
 
 
@@ -48,8 +47,8 @@ type CommonAPIClient interface {
 type ContainerAPIClient interface {
 type ContainerAPIClient interface {
 	ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error)
 	ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error)
 	ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error)
 	ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error)
-	ContainerCreate(ctx context.Context, config *containertypes.Config, hostConfig *containertypes.HostConfig, networkingConfig *networktypes.NetworkingConfig, platform *specs.Platform, containerName string) (containertypes.ContainerCreateCreatedBody, error)
-	ContainerDiff(ctx context.Context, container string) ([]containertypes.ContainerChangeResponseItem, error)
+	ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *specs.Platform, containerName string) (container.ContainerCreateCreatedBody, error)
+	ContainerDiff(ctx context.Context, container string) ([]container.ContainerChangeResponseItem, error)
 	ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error)
 	ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error)
 	ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error)
 	ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error)
 	ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error)
 	ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error)
@@ -65,16 +64,16 @@ type ContainerAPIClient interface {
 	ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error
 	ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error
 	ContainerRename(ctx context.Context, container, newContainerName string) error
 	ContainerRename(ctx context.Context, container, newContainerName string) error
 	ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error
 	ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error
-	ContainerRestart(ctx context.Context, container string, timeout *time.Duration) error
+	ContainerRestart(ctx context.Context, container string, options container.StopOptions) error
 	ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error)
 	ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error)
 	ContainerStats(ctx context.Context, container string, stream bool) (types.ContainerStats, error)
 	ContainerStats(ctx context.Context, container string, stream bool) (types.ContainerStats, error)
 	ContainerStatsOneShot(ctx context.Context, container string) (types.ContainerStats, error)
 	ContainerStatsOneShot(ctx context.Context, container string) (types.ContainerStats, error)
 	ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error
 	ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error
-	ContainerStop(ctx context.Context, container string, timeout *time.Duration) error
-	ContainerTop(ctx context.Context, container string, arguments []string) (containertypes.ContainerTopOKBody, error)
+	ContainerStop(ctx context.Context, container string, options container.StopOptions) error
+	ContainerTop(ctx context.Context, container string, arguments []string) (container.ContainerTopOKBody, error)
 	ContainerUnpause(ctx context.Context, container string) error
 	ContainerUnpause(ctx context.Context, container string) error
-	ContainerUpdate(ctx context.Context, container string, updateConfig containertypes.UpdateConfig) (containertypes.ContainerUpdateOKBody, error)
-	ContainerWait(ctx context.Context, container string, condition containertypes.WaitCondition) (<-chan containertypes.ContainerWaitOKBody, <-chan error)
+	ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error)
+	ContainerWait(ctx context.Context, container string, condition container.WaitCondition) (<-chan container.ContainerWaitOKBody, <-chan error)
 	CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
 	CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
 	CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
 	CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
 	ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error)
 	ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error)
@@ -107,7 +106,7 @@ type ImageAPIClient interface {
 
 
 // NetworkAPIClient defines API client methods for the networks
 // NetworkAPIClient defines API client methods for the networks
 type NetworkAPIClient interface {
 type NetworkAPIClient interface {
-	NetworkConnect(ctx context.Context, network, container string, config *networktypes.EndpointSettings) error
+	NetworkConnect(ctx context.Context, network, container string, config *network.EndpointSettings) error
 	NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
 	NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
 	NetworkDisconnect(ctx context.Context, network, container string, force bool) error
 	NetworkDisconnect(ctx context.Context, network, container string, force bool) error
 	NetworkInspect(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, error)
 	NetworkInspect(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, error)
@@ -174,10 +173,10 @@ type SystemAPIClient interface {
 
 
 // VolumeAPIClient defines API client methods for the volumes
 // VolumeAPIClient defines API client methods for the volumes
 type VolumeAPIClient interface {
 type VolumeAPIClient interface {
-	VolumeCreate(ctx context.Context, options volumetypes.VolumeCreateBody) (types.Volume, error)
+	VolumeCreate(ctx context.Context, options volume.VolumeCreateBody) (types.Volume, error)
 	VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error)
 	VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error)
 	VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error)
 	VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error)
-	VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumeListOKBody, error)
+	VolumeList(ctx context.Context, filter filters.Args) (volume.VolumeListOKBody, error)
 	VolumeRemove(ctx context.Context, volumeID string, force bool) error
 	VolumeRemove(ctx context.Context, volumeID string, force bool) error
 	VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error)
 	VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error)
 }
 }

+ 2 - 2
daemon/cluster/executor/backend.go

@@ -35,8 +35,8 @@ type Backend interface {
 	ReleaseIngress() (<-chan struct{}, error)
 	ReleaseIngress() (<-chan struct{}, error)
 	CreateManagedContainer(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error)
 	CreateManagedContainer(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error)
 	ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
 	ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
-	ContainerStop(name string, seconds *int) error
-	ContainerLogs(context.Context, string, *types.ContainerLogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
+	ContainerStop(ctx context.Context, name string, config container.StopOptions) error
+	ContainerLogs(ctx context.Context, name string, config *types.ContainerLogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
 	ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
 	ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
 	ActivateContainerServiceBinding(containerName string) error
 	ActivateContainerServiceBinding(containerName string) error
 	DeactivateContainerServiceBinding(containerName string) error
 	DeactivateContainerServiceBinding(containerName string) error

+ 5 - 6
daemon/cluster/executor/container/adapter.go

@@ -407,14 +407,13 @@ func (c *containerAdapter) wait(ctx context.Context) (<-chan containerpkg.StateS
 }
 }
 
 
 func (c *containerAdapter) shutdown(ctx context.Context) error {
 func (c *containerAdapter) shutdown(ctx context.Context) error {
+	var options = containertypes.StopOptions{}
 	// Default stop grace period to nil (daemon will use the stopTimeout of the container)
 	// Default stop grace period to nil (daemon will use the stopTimeout of the container)
-	var stopgrace *int
-	spec := c.container.spec()
-	if spec.StopGracePeriod != nil {
-		stopgraceValue := int(spec.StopGracePeriod.Seconds)
-		stopgrace = &stopgraceValue
+	if spec := c.container.spec(); spec.StopGracePeriod != nil {
+		timeout := int(spec.StopGracePeriod.Seconds)
+		options.Timeout = &timeout
 	}
 	}
-	return c.backend.ContainerStop(c.container.name(), stopgrace)
+	return c.backend.ContainerStop(ctx, c.container.name(), options)
 }
 }
 
 
 func (c *containerAdapter) terminate(ctx context.Context) error {
 func (c *containerAdapter) terminate(ctx context.Context) error {

+ 5 - 5
daemon/content.go

@@ -12,19 +12,19 @@ import (
 	"go.etcd.io/bbolt"
 	"go.etcd.io/bbolt"
 )
 )
 
 
-func (d *Daemon) configureLocalContentStore() (content.Store, leases.Manager, error) {
-	if err := os.MkdirAll(filepath.Join(d.root, "content"), 0700); err != nil {
+func (daemon *Daemon) configureLocalContentStore() (content.Store, leases.Manager, error) {
+	if err := os.MkdirAll(filepath.Join(daemon.root, "content"), 0700); err != nil {
 		return nil, nil, errors.Wrap(err, "error creating dir for content store")
 		return nil, nil, errors.Wrap(err, "error creating dir for content store")
 	}
 	}
-	db, err := bbolt.Open(filepath.Join(d.root, "content", "metadata.db"), 0600, nil)
+	db, err := bbolt.Open(filepath.Join(daemon.root, "content", "metadata.db"), 0600, nil)
 	if err != nil {
 	if err != nil {
 		return nil, nil, errors.Wrap(err, "error opening bolt db for content metadata store")
 		return nil, nil, errors.Wrap(err, "error opening bolt db for content metadata store")
 	}
 	}
-	cs, err := local.NewStore(filepath.Join(d.root, "content", "data"))
+	cs, err := local.NewStore(filepath.Join(daemon.root, "content", "data"))
 	if err != nil {
 	if err != nil {
 		return nil, nil, errors.Wrap(err, "error setting up content store")
 		return nil, nil, errors.Wrap(err, "error setting up content store")
 	}
 	}
 	md := metadata.NewDB(db, cs, nil)
 	md := metadata.NewDB(db, cs, nil)
-	d.mdDB = db
+	daemon.mdDB = db
 	return md.ContentStore(), metadata.NewLeaseManager(md), nil
 	return md.ContentStore(), metadata.NewLeaseManager(md), nil
 }
 }

+ 6 - 2
daemon/create.go

@@ -153,8 +153,12 @@ func (daemon *Daemon) create(opts createOpts) (retC *container.Container, retErr
 	}
 	}
 	defer func() {
 	defer func() {
 		if retErr != nil {
 		if retErr != nil {
-			if err := daemon.cleanupContainer(ctr, true, true); err != nil {
-				logrus.Errorf("failed to cleanup container on create error: %v", err)
+			err = daemon.cleanupContainer(ctr, types.ContainerRmConfig{
+				ForceRemove:  true,
+				RemoveVolume: true,
+			})
+			if err != nil {
+				logrus.WithError(err).Error("failed to cleanup container on create error")
 			}
 			}
 		}
 		}
 	}()
 	}()

+ 1 - 3
daemon/daemon.go

@@ -1116,10 +1116,8 @@ func (daemon *Daemon) waitForStartupDone() {
 }
 }
 
 
 func (daemon *Daemon) shutdownContainer(c *container.Container) error {
 func (daemon *Daemon) shutdownContainer(c *container.Container) error {
-	stopTimeout := c.StopTimeout()
-
 	// If container failed to exit in stopTimeout seconds of SIGTERM, then using the force
 	// If container failed to exit in stopTimeout seconds of SIGTERM, then using the force
-	if err := daemon.containerStop(c, stopTimeout); err != nil {
+	if err := daemon.containerStop(context.TODO(), c, containertypes.StopOptions{}); err != nil {
 		return fmt.Errorf("Failed to stop container %s with error: %v", c.ID, err)
 		return fmt.Errorf("Failed to stop container %s with error: %v", c.ID, err)
 	}
 	}
 
 

+ 24 - 10
daemon/delete.go

@@ -1,6 +1,7 @@
 package daemon // import "github.com/docker/docker/daemon"
 package daemon // import "github.com/docker/docker/daemon"
 
 
 import (
 import (
+	"context"
 	"fmt"
 	"fmt"
 	"os"
 	"os"
 	"path"
 	"path"
@@ -8,6 +9,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
+	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/pkg/containerfs"
 	"github.com/docker/docker/pkg/containerfs"
@@ -22,28 +24,28 @@ import (
 // network links are removed.
 // network links are removed.
 func (daemon *Daemon) ContainerRm(name string, config *types.ContainerRmConfig) error {
 func (daemon *Daemon) ContainerRm(name string, config *types.ContainerRmConfig) error {
 	start := time.Now()
 	start := time.Now()
-	container, err := daemon.GetContainer(name)
+	ctr, err := daemon.GetContainer(name)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
 	// Container state RemovalInProgress should be used to avoid races.
 	// Container state RemovalInProgress should be used to avoid races.
-	if inProgress := container.SetRemovalInProgress(); inProgress {
+	if inProgress := ctr.SetRemovalInProgress(); inProgress {
 		err := fmt.Errorf("removal of container %s is already in progress", name)
 		err := fmt.Errorf("removal of container %s is already in progress", name)
 		return errdefs.Conflict(err)
 		return errdefs.Conflict(err)
 	}
 	}
-	defer container.ResetRemovalInProgress()
+	defer ctr.ResetRemovalInProgress()
 
 
 	// check if container wasn't deregistered by previous rm since Get
 	// check if container wasn't deregistered by previous rm since Get
-	if c := daemon.containers.Get(container.ID); c == nil {
+	if c := daemon.containers.Get(ctr.ID); c == nil {
 		return nil
 		return nil
 	}
 	}
 
 
 	if config.RemoveLink {
 	if config.RemoveLink {
-		return daemon.rmLink(container, name)
+		return daemon.rmLink(ctr, name)
 	}
 	}
 
 
-	err = daemon.cleanupContainer(container, config.ForceRemove, config.RemoveVolume)
+	err = daemon.cleanupContainer(ctr, *config)
 	containerActions.WithValues("delete").UpdateSince(start)
 	containerActions.WithValues("delete").UpdateSince(start)
 
 
 	return err
 	return err
@@ -77,9 +79,9 @@ func (daemon *Daemon) rmLink(container *container.Container, name string) error
 
 
 // cleanupContainer unregisters a container from the daemon, stops stats
 // cleanupContainer unregisters a container from the daemon, stops stats
 // collection and cleanly removes contents and metadata from the filesystem.
 // collection and cleanly removes contents and metadata from the filesystem.
-func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemove, removeVolume bool) error {
+func (daemon *Daemon) cleanupContainer(container *container.Container, config types.ContainerRmConfig) error {
 	if container.IsRunning() {
 	if container.IsRunning() {
-		if !forceRemove {
+		if !config.ForceRemove {
 			state := container.StateString()
 			state := container.StateString()
 			procedure := "Stop the container before attempting removal or force remove"
 			procedure := "Stop the container before attempting removal or force remove"
 			if state == "paused" {
 			if state == "paused" {
@@ -97,7 +99,19 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo
 	// if stats are currently getting collected.
 	// if stats are currently getting collected.
 	daemon.statsCollector.StopCollection(container)
 	daemon.statsCollector.StopCollection(container)
 
 
-	if err := daemon.containerStop(container, 3); err != nil {
+	// stopTimeout is the number of seconds to wait for the container to stop
+	// gracefully before forcibly killing it.
+	//
+	// Why 3 seconds? The timeout specified here was originally added in commit
+	// 1615bb08c7c3fc6c4b22db0a633edda516f97cf0, which added a custom timeout to
+	// some commands, but lacking an option for a timeout on "docker rm", was
+	// hardcoded to 10 seconds. Commit 28fd289b448164b77affd8103c0d96fd8110daf9
+	// later on updated this to 3 seconds (but no background on that change).
+	//
+	// If you arrived here and know the answer, you earned yourself a picture
+	// of a cute animal of your own choosing.
+	var stopTimeout = 3
+	if err := daemon.containerStop(context.TODO(), container, containertypes.StopOptions{Timeout: &stopTimeout}); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -135,7 +149,7 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo
 	daemon.idIndex.Delete(container.ID)
 	daemon.idIndex.Delete(container.ID)
 	daemon.containers.Delete(container.ID)
 	daemon.containers.Delete(container.ID)
 	daemon.containersReplica.Delete(container)
 	daemon.containersReplica.Delete(container)
-	if err := daemon.removeMountPoints(container, removeVolume); err != nil {
+	if err := daemon.removeMountPoints(container, config.RemoveVolume); err != nil {
 		logrus.Error(err)
 		logrus.Error(err)
 	}
 	}
 	for _, name := range linkNames {
 	for _, name := range linkNames {

+ 6 - 9
daemon/restart.go

@@ -1,6 +1,7 @@
 package daemon // import "github.com/docker/docker/daemon"
 package daemon // import "github.com/docker/docker/daemon"
 
 
 import (
 import (
+	"context"
 	"fmt"
 	"fmt"
 
 
 	containertypes "github.com/docker/docker/api/types/container"
 	containertypes "github.com/docker/docker/api/types/container"
@@ -14,16 +15,13 @@ import (
 // timeout, ContainerRestart will wait forever until a graceful
 // timeout, ContainerRestart will wait forever until a graceful
 // stop. Returns an error if the container cannot be found, or if
 // stop. Returns an error if the container cannot be found, or if
 // there is an underlying error at any stage of the restart.
 // there is an underlying error at any stage of the restart.
-func (daemon *Daemon) ContainerRestart(name string, seconds *int) error {
+func (daemon *Daemon) ContainerRestart(ctx context.Context, name string, options containertypes.StopOptions) error {
 	ctr, err := daemon.GetContainer(name)
 	ctr, err := daemon.GetContainer(name)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	if seconds == nil {
-		stopTimeout := ctr.StopTimeout()
-		seconds = &stopTimeout
-	}
-	if err := daemon.containerRestart(ctr, *seconds); err != nil {
+	err = daemon.containerRestart(ctx, ctr, options)
+	if err != nil {
 		return fmt.Errorf("Cannot restart container %s: %v", name, err)
 		return fmt.Errorf("Cannot restart container %s: %v", name, err)
 	}
 	}
 	return nil
 	return nil
@@ -34,8 +32,7 @@ func (daemon *Daemon) ContainerRestart(name string, seconds *int) error {
 // container. When stopping, wait for the given duration in seconds to
 // container. When stopping, wait for the given duration in seconds to
 // gracefully stop, before forcefully terminating the container. If
 // gracefully stop, before forcefully terminating the container. If
 // given a negative duration, wait forever for a graceful stop.
 // given a negative duration, wait forever for a graceful stop.
-func (daemon *Daemon) containerRestart(container *container.Container, seconds int) error {
-
+func (daemon *Daemon) containerRestart(ctx context.Context, container *container.Container, options containertypes.StopOptions) error {
 	// Determine isolation. If not specified in the hostconfig, use daemon default.
 	// Determine isolation. If not specified in the hostconfig, use daemon default.
 	actualIsolation := container.HostConfig.Isolation
 	actualIsolation := container.HostConfig.Isolation
 	if containertypes.Isolation.IsDefault(actualIsolation) {
 	if containertypes.Isolation.IsDefault(actualIsolation) {
@@ -60,7 +57,7 @@ func (daemon *Daemon) containerRestart(container *container.Container, seconds i
 		autoRemove := container.HostConfig.AutoRemove
 		autoRemove := container.HostConfig.AutoRemove
 
 
 		container.HostConfig.AutoRemove = false
 		container.HostConfig.AutoRemove = false
-		err := daemon.containerStop(container, seconds)
+		err := daemon.containerStop(ctx, container, options)
 		// restore AutoRemove irrespective of whether the stop worked or not
 		// restore AutoRemove irrespective of whether the stop worked or not
 		container.HostConfig.AutoRemove = autoRemove
 		container.HostConfig.AutoRemove = autoRemove
 		// containerStop will write HostConfig to disk, we shall restore AutoRemove
 		// containerStop will write HostConfig to disk, we shall restore AutoRemove

+ 29 - 29
daemon/seccomp_linux_test.go

@@ -7,10 +7,10 @@ import (
 	"testing"
 	"testing"
 
 
 	coci "github.com/containerd/containerd/oci"
 	coci "github.com/containerd/containerd/oci"
-	config "github.com/docker/docker/api/types/container"
+	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/container"
 	dconfig "github.com/docker/docker/daemon/config"
 	dconfig "github.com/docker/docker/daemon/config"
-	doci "github.com/docker/docker/oci"
+	"github.com/docker/docker/oci"
 	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/profiles/seccomp"
 	"github.com/docker/docker/profiles/seccomp"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
@@ -36,12 +36,12 @@ func TestWithSeccomp(t *testing.T) {
 			},
 			},
 			c: &container.Container{
 			c: &container.Container{
 				SeccompProfile: dconfig.SeccompProfileUnconfined,
 				SeccompProfile: dconfig.SeccompProfileUnconfined,
-				HostConfig: &config.HostConfig{
+				HostConfig: &containertypes.HostConfig{
 					Privileged: false,
 					Privileged: false,
 				},
 				},
 			},
 			},
-			inSpec:  doci.DefaultLinuxSpec(),
-			outSpec: doci.DefaultLinuxSpec(),
+			inSpec:  oci.DefaultLinuxSpec(),
+			outSpec: oci.DefaultLinuxSpec(),
 		},
 		},
 		{
 		{
 			comment: "privileged container w/ custom profile runs unconfined",
 			comment: "privileged container w/ custom profile runs unconfined",
@@ -50,12 +50,12 @@ func TestWithSeccomp(t *testing.T) {
 			},
 			},
 			c: &container.Container{
 			c: &container.Container{
 				SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_LOG\" }",
 				SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_LOG\" }",
-				HostConfig: &config.HostConfig{
+				HostConfig: &containertypes.HostConfig{
 					Privileged: true,
 					Privileged: true,
 				},
 				},
 			},
 			},
-			inSpec:  doci.DefaultLinuxSpec(),
-			outSpec: doci.DefaultLinuxSpec(),
+			inSpec:  oci.DefaultLinuxSpec(),
+			outSpec: oci.DefaultLinuxSpec(),
 		},
 		},
 		{
 		{
 			comment: "privileged container w/ default runs unconfined",
 			comment: "privileged container w/ default runs unconfined",
@@ -64,12 +64,12 @@ func TestWithSeccomp(t *testing.T) {
 			},
 			},
 			c: &container.Container{
 			c: &container.Container{
 				SeccompProfile: "",
 				SeccompProfile: "",
-				HostConfig: &config.HostConfig{
+				HostConfig: &containertypes.HostConfig{
 					Privileged: true,
 					Privileged: true,
 				},
 				},
 			},
 			},
-			inSpec:  doci.DefaultLinuxSpec(),
-			outSpec: doci.DefaultLinuxSpec(),
+			inSpec:  oci.DefaultLinuxSpec(),
+			outSpec: oci.DefaultLinuxSpec(),
 		},
 		},
 		{
 		{
 			comment: "privileged container w/ daemon profile runs unconfined",
 			comment: "privileged container w/ daemon profile runs unconfined",
@@ -79,12 +79,12 @@ func TestWithSeccomp(t *testing.T) {
 			},
 			},
 			c: &container.Container{
 			c: &container.Container{
 				SeccompProfile: "",
 				SeccompProfile: "",
-				HostConfig: &config.HostConfig{
+				HostConfig: &containertypes.HostConfig{
 					Privileged: true,
 					Privileged: true,
 				},
 				},
 			},
 			},
-			inSpec:  doci.DefaultLinuxSpec(),
-			outSpec: doci.DefaultLinuxSpec(),
+			inSpec:  oci.DefaultLinuxSpec(),
+			outSpec: oci.DefaultLinuxSpec(),
 		},
 		},
 		{
 		{
 			comment: "custom profile when seccomp is disabled returns error",
 			comment: "custom profile when seccomp is disabled returns error",
@@ -93,12 +93,12 @@ func TestWithSeccomp(t *testing.T) {
 			},
 			},
 			c: &container.Container{
 			c: &container.Container{
 				SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_ERRNO\" }",
 				SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_ERRNO\" }",
-				HostConfig: &config.HostConfig{
+				HostConfig: &containertypes.HostConfig{
 					Privileged: false,
 					Privileged: false,
 				},
 				},
 			},
 			},
-			inSpec:  doci.DefaultLinuxSpec(),
-			outSpec: doci.DefaultLinuxSpec(),
+			inSpec:  oci.DefaultLinuxSpec(),
+			outSpec: oci.DefaultLinuxSpec(),
 			err:     "seccomp is not enabled in your kernel, cannot run a custom seccomp profile",
 			err:     "seccomp is not enabled in your kernel, cannot run a custom seccomp profile",
 		},
 		},
 		{
 		{
@@ -108,13 +108,13 @@ func TestWithSeccomp(t *testing.T) {
 			},
 			},
 			c: &container.Container{
 			c: &container.Container{
 				SeccompProfile: "",
 				SeccompProfile: "",
-				HostConfig: &config.HostConfig{
+				HostConfig: &containertypes.HostConfig{
 					Privileged: false,
 					Privileged: false,
 				},
 				},
 			},
 			},
-			inSpec: doci.DefaultLinuxSpec(),
+			inSpec: oci.DefaultLinuxSpec(),
 			outSpec: func() coci.Spec {
 			outSpec: func() coci.Spec {
-				s := doci.DefaultLinuxSpec()
+				s := oci.DefaultLinuxSpec()
 				profile, _ := seccomp.GetDefaultProfile(&s)
 				profile, _ := seccomp.GetDefaultProfile(&s)
 				s.Linux.Seccomp = profile
 				s.Linux.Seccomp = profile
 				return s
 				return s
@@ -127,13 +127,13 @@ func TestWithSeccomp(t *testing.T) {
 			},
 			},
 			c: &container.Container{
 			c: &container.Container{
 				SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_ERRNO\" }",
 				SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_ERRNO\" }",
-				HostConfig: &config.HostConfig{
+				HostConfig: &containertypes.HostConfig{
 					Privileged: false,
 					Privileged: false,
 				},
 				},
 			},
 			},
-			inSpec: doci.DefaultLinuxSpec(),
+			inSpec: oci.DefaultLinuxSpec(),
 			outSpec: func() coci.Spec {
 			outSpec: func() coci.Spec {
-				s := doci.DefaultLinuxSpec()
+				s := oci.DefaultLinuxSpec()
 				profile := &specs.LinuxSeccomp{
 				profile := &specs.LinuxSeccomp{
 					DefaultAction: specs.LinuxSeccompAction("SCMP_ACT_ERRNO"),
 					DefaultAction: specs.LinuxSeccompAction("SCMP_ACT_ERRNO"),
 				}
 				}
@@ -149,13 +149,13 @@ func TestWithSeccomp(t *testing.T) {
 			},
 			},
 			c: &container.Container{
 			c: &container.Container{
 				SeccompProfile: "",
 				SeccompProfile: "",
-				HostConfig: &config.HostConfig{
+				HostConfig: &containertypes.HostConfig{
 					Privileged: false,
 					Privileged: false,
 				},
 				},
 			},
 			},
-			inSpec: doci.DefaultLinuxSpec(),
+			inSpec: oci.DefaultLinuxSpec(),
 			outSpec: func() coci.Spec {
 			outSpec: func() coci.Spec {
-				s := doci.DefaultLinuxSpec()
+				s := oci.DefaultLinuxSpec()
 				profile := &specs.LinuxSeccomp{
 				profile := &specs.LinuxSeccomp{
 					DefaultAction: specs.LinuxSeccompAction("SCMP_ACT_ERRNO"),
 					DefaultAction: specs.LinuxSeccompAction("SCMP_ACT_ERRNO"),
 				}
 				}
@@ -171,13 +171,13 @@ func TestWithSeccomp(t *testing.T) {
 			},
 			},
 			c: &container.Container{
 			c: &container.Container{
 				SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_LOG\" }",
 				SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_LOG\" }",
-				HostConfig: &config.HostConfig{
+				HostConfig: &containertypes.HostConfig{
 					Privileged: false,
 					Privileged: false,
 				},
 				},
 			},
 			},
-			inSpec: doci.DefaultLinuxSpec(),
+			inSpec: oci.DefaultLinuxSpec(),
 			outSpec: func() coci.Spec {
 			outSpec: func() coci.Spec {
-				s := doci.DefaultLinuxSpec()
+				s := oci.DefaultLinuxSpec()
 				profile := &specs.LinuxSeccomp{
 				profile := &specs.LinuxSeccomp{
 					DefaultAction: specs.LinuxSeccompAction("SCMP_ACT_LOG"),
 					DefaultAction: specs.LinuxSeccompAction("SCMP_ACT_LOG"),
 				}
 				}

+ 50 - 36
daemon/stop.go

@@ -4,8 +4,10 @@ import (
 	"context"
 	"context"
 	"time"
 	"time"
 
 
-	containerpkg "github.com/docker/docker/container"
+	containertypes "github.com/docker/docker/api/types/container"
+	"github.com/docker/docker/container"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/errdefs"
+	"github.com/moby/sys/signal"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 )
 )
@@ -18,84 +20,96 @@ import (
 // If the timeout is nil, the container's StopTimeout value is used, if set,
 // If the timeout is nil, the container's StopTimeout value is used, if set,
 // otherwise the engine default. A negative timeout value can be specified,
 // otherwise the engine default. A negative timeout value can be specified,
 // meaning no timeout, i.e. no forceful termination is performed.
 // meaning no timeout, i.e. no forceful termination is performed.
-func (daemon *Daemon) ContainerStop(name string, timeout *int) error {
-	container, err := daemon.GetContainer(name)
+func (daemon *Daemon) ContainerStop(ctx context.Context, name string, options containertypes.StopOptions) error {
+	ctr, err := daemon.GetContainer(name)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	if !container.IsRunning() {
-		return containerNotModifiedError{running: false}
+	if !ctr.IsRunning() {
+		return containerNotModifiedError{}
 	}
 	}
-	if timeout == nil {
-		stopTimeout := container.StopTimeout()
-		timeout = &stopTimeout
-	}
-	if err := daemon.containerStop(container, *timeout); err != nil {
+	err = daemon.containerStop(ctx, ctr, options)
+	if err != nil {
 		return errdefs.System(errors.Wrapf(err, "cannot stop container: %s", name))
 		return errdefs.System(errors.Wrapf(err, "cannot stop container: %s", name))
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
 // containerStop sends a stop signal, waits, sends a kill signal.
 // containerStop sends a stop signal, waits, sends a kill signal.
-func (daemon *Daemon) containerStop(container *containerpkg.Container, seconds int) error {
-	// TODO propagate a context down to this function
-	ctx := context.TODO()
-	if !container.IsRunning() {
+func (daemon *Daemon) containerStop(ctx context.Context, ctr *container.Container, options containertypes.StopOptions) (retErr error) {
+	if !ctr.IsRunning() {
 		return nil
 		return nil
 	}
 	}
-	var wait time.Duration
-	if seconds >= 0 {
-		wait = time.Duration(seconds) * time.Second
+
+	var (
+		stopSignal  = ctr.StopSignal()
+		stopTimeout = ctr.StopTimeout()
+	)
+	if options.Signal != "" {
+		sig, err := signal.ParseSignal(options.Signal)
+		if err != nil {
+			return errdefs.InvalidParameter(err)
+		}
+		stopSignal = int(sig)
 	}
 	}
-	success := func() error {
-		daemon.LogContainerEvent(container, "stop")
-		return nil
+	if options.Timeout != nil {
+		stopTimeout = *options.Timeout
+	}
+
+	var wait time.Duration
+	if stopTimeout >= 0 {
+		wait = time.Duration(stopTimeout) * time.Second
 	}
 	}
-	stopSignal := container.StopSignal()
+	defer func() {
+		if retErr == nil {
+			daemon.LogContainerEvent(ctr, "stop")
+		}
+	}()
 
 
 	// 1. Send a stop signal
 	// 1. Send a stop signal
-	err := daemon.killPossiblyDeadProcess(container, stopSignal)
+	err := daemon.killPossiblyDeadProcess(ctr, stopSignal)
 	if err != nil {
 	if err != nil {
 		wait = 2 * time.Second
 		wait = 2 * time.Second
 	}
 	}
 
 
 	var subCtx context.Context
 	var subCtx context.Context
 	var cancel context.CancelFunc
 	var cancel context.CancelFunc
-	if seconds >= 0 {
+	if stopTimeout >= 0 {
 		subCtx, cancel = context.WithTimeout(ctx, wait)
 		subCtx, cancel = context.WithTimeout(ctx, wait)
 	} else {
 	} else {
 		subCtx, cancel = context.WithCancel(ctx)
 		subCtx, cancel = context.WithCancel(ctx)
 	}
 	}
 	defer cancel()
 	defer cancel()
 
 
-	if status := <-container.Wait(subCtx, containerpkg.WaitConditionNotRunning); status.Err() == nil {
+	if status := <-ctr.Wait(subCtx, container.WaitConditionNotRunning); status.Err() == nil {
 		// container did exit, so ignore any previous errors and return
 		// container did exit, so ignore any previous errors and return
-		return success()
+		return nil
 	}
 	}
 
 
 	if err != nil {
 	if err != nil {
 		// the container has still not exited, and the kill function errored, so log the error here:
 		// the container has still not exited, and the kill function errored, so log the error here:
-		logrus.WithError(err).WithField("container", container.ID).Errorf("Error sending stop (signal %d) to container", stopSignal)
+		logrus.WithError(err).WithField("container", ctr.ID).Errorf("Error sending stop (signal %d) to container", stopSignal)
 	}
 	}
-	if seconds < 0 {
+	if stopTimeout < 0 {
 		// if the client requested that we never kill / wait forever, but container.Wait was still
 		// if the client requested that we never kill / wait forever, but container.Wait was still
 		// interrupted (parent context cancelled, for example), we should propagate the signal failure
 		// interrupted (parent context cancelled, for example), we should propagate the signal failure
 		return err
 		return err
 	}
 	}
 
 
-	logrus.WithField("container", container.ID).Infof("Container failed to exit within %s of signal %d - using the force", wait, stopSignal)
-	// Stop either failed or container didnt exit, so fallback to kill.
-	if err := daemon.Kill(container); err != nil {
+	logrus.WithField("container", ctr.ID).Infof("Container failed to exit within %s of signal %d - using the force", wait, stopSignal)
+
+	// Stop either failed or container didn't exit, so fallback to kill.
+	if err := daemon.Kill(ctr); err != nil {
 		// got a kill error, but give container 2 more seconds to exit just in case
 		// got a kill error, but give container 2 more seconds to exit just in case
 		subCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
 		subCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
 		defer cancel()
 		defer cancel()
-		if status := <-container.Wait(subCtx, containerpkg.WaitConditionNotRunning); status.Err() == nil {
-			// container did exit, so ignore error and return
-			return success()
+		status := <-ctr.Wait(subCtx, container.WaitConditionNotRunning)
+		if status.Err() != nil {
+			logrus.WithError(err).WithField("container", ctr.ID).Errorf("error killing container: %v", status.Err())
+			return err
 		}
 		}
-		logrus.WithError(err).WithField("container", container.ID).Error("Error killing the container")
-		return err
+		// container did exit, so ignore previous errors and continue
 	}
 	}
 
 
-	return success()
+	return nil
 }
 }

+ 3 - 0
docs/api/version-history.md

@@ -21,6 +21,9 @@ keywords: "API, Docker, rcli, REST, documentation"
   was introduced in API 1.31 as part of an experimental feature, and no longer
   was introduced in API 1.31 as part of an experimental feature, and no longer
   used since API 1.40.
   used since API 1.40.
   Use field `BuildCache` instead to track storage used by the builder component.
   Use field `BuildCache` instead to track storage used by the builder component.
+* `POST /containers/{id}/stop` and `POST /containers/{id}/restart` now accept a
+  `signal` query parameter, which allows overriding the container's default stop-
+  signal.
 * `GET /images/json` now accepts query parameter `shared-size`. When set `true`,
 * `GET /images/json` now accepts query parameter `shared-size`. When set `true`,
   images returned will include `SharedSize`, which provides the size on disk shared
   images returned will include `SharedSize`, which provides the size on disk shared
   with other images present on the system.
   with other images present on the system.

+ 168 - 164
integration-cli/docker_api_containers_test.go

@@ -17,9 +17,9 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
-	containertypes "github.com/docker/docker/api/types/container"
-	mounttypes "github.com/docker/docker/api/types/mount"
-	networktypes "github.com/docker/docker/api/types/network"
+	"github.com/docker/docker/api/types/container"
+	"github.com/docker/docker/api/types/mount"
+	"github.com/docker/docker/api/types/network"
 	"github.com/docker/docker/api/types/versions"
 	"github.com/docker/docker/api/types/versions"
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/client"
 	dconfig "github.com/docker/docker/daemon/config"
 	dconfig "github.com/docker/docker/daemon/config"
@@ -476,7 +476,7 @@ func (s *DockerSuite) TestContainerAPICommitWithLabelInConfig(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	config := containertypes.Config{
+	config := container.Config{
 		Labels: map[string]string{"key1": "value1", "key2": "value2"}}
 		Labels: map[string]string{"key1": "value1", "key2": "value2"}}
 
 
 	options := types.ContainerCommitOptions{
 	options := types.ContainerCommitOptions{
@@ -504,12 +504,12 @@ func (s *DockerSuite) TestContainerAPIBadPort(c *testing.T) {
 	// TODO Windows to Windows CI - Port this test
 	// TODO Windows to Windows CI - Port this test
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
 
 
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 		Cmd:   []string{"/bin/sh", "-c", "echo test"},
 		Cmd:   []string{"/bin/sh", "-c", "echo test"},
 	}
 	}
 
 
-	hostConfig := containertypes.HostConfig{
+	hostConfig := container.HostConfig{
 		PortBindings: nat.PortMap{
 		PortBindings: nat.PortMap{
 			"8080/tcp": []nat.PortBinding{
 			"8080/tcp": []nat.PortBinding{
 				{
 				{
@@ -523,12 +523,12 @@ func (s *DockerSuite) TestContainerAPIBadPort(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "")
+	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
 	assert.ErrorContains(c, err, `invalid port specification: "aa80"`)
 	assert.ErrorContains(c, err, `invalid port specification: "aa80"`)
 }
 }
 
 
 func (s *DockerSuite) TestContainerAPICreate(c *testing.T) {
 func (s *DockerSuite) TestContainerAPICreate(c *testing.T) {
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 		Cmd:   []string{"/bin/sh", "-c", "touch /test && ls /test"},
 		Cmd:   []string{"/bin/sh", "-c", "touch /test && ls /test"},
 	}
 	}
@@ -537,7 +537,7 @@ func (s *DockerSuite) TestContainerAPICreate(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
+	container, err := cli.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	out, _ := dockerCmd(c, "start", "-a", container.ID)
 	out, _ := dockerCmd(c, "start", "-a", container.ID)
@@ -550,7 +550,7 @@ func (s *DockerSuite) TestContainerAPICreateEmptyConfig(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	_, err = cli.ContainerCreate(context.Background(), &containertypes.Config{}, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
+	_, err = cli.ContainerCreate(context.Background(), &container.Config{}, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
 
 
 	expected := "No command specified"
 	expected := "No command specified"
 	assert.ErrorContains(c, err, expected)
 	assert.ErrorContains(c, err, expected)
@@ -558,12 +558,12 @@ func (s *DockerSuite) TestContainerAPICreateEmptyConfig(c *testing.T) {
 
 
 func (s *DockerSuite) TestContainerAPICreateMultipleNetworksConfig(c *testing.T) {
 func (s *DockerSuite) TestContainerAPICreateMultipleNetworksConfig(c *testing.T) {
 	// Container creation must fail if client specified configurations for more than one network
 	// Container creation must fail if client specified configurations for more than one network
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 	}
 	}
 
 
-	networkingConfig := networktypes.NetworkingConfig{
-		EndpointsConfig: map[string]*networktypes.EndpointSettings{
+	networkingConfig := network.NetworkingConfig{
+		EndpointsConfig: map[string]*network.EndpointSettings{
 			"net1": {},
 			"net1": {},
 			"net2": {},
 			"net2": {},
 			"net3": {},
 			"net3": {},
@@ -574,7 +574,7 @@ func (s *DockerSuite) TestContainerAPICreateMultipleNetworksConfig(c *testing.T)
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networkingConfig, nil, "")
+	_, err = cli.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &networkingConfig, nil, "")
 	msg := err.Error()
 	msg := err.Error()
 	// network name order in error message is not deterministic
 	// network name order in error message is not deterministic
 	assert.Assert(c, strings.Contains(msg, "Container cannot be connected to network endpoints"))
 	assert.Assert(c, strings.Contains(msg, "Container cannot be connected to network endpoints"))
@@ -596,12 +596,12 @@ func (s *DockerSuite) TestContainerAPICreateOtherNetworkModes(c *testing.T) {
 	UtilCreateNetworkMode(c, "container:web1")
 	UtilCreateNetworkMode(c, "container:web1")
 }
 }
 
 
-func UtilCreateNetworkMode(c *testing.T, networkMode containertypes.NetworkMode) {
-	config := containertypes.Config{
+func UtilCreateNetworkMode(c *testing.T, networkMode container.NetworkMode) {
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 	}
 	}
 
 
-	hostConfig := containertypes.HostConfig{
+	hostConfig := container.HostConfig{
 		NetworkMode: networkMode,
 		NetworkMode: networkMode,
 	}
 	}
 
 
@@ -609,7 +609,7 @@ func UtilCreateNetworkMode(c *testing.T, networkMode containertypes.NetworkMode)
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "")
+	container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
@@ -621,12 +621,12 @@ func UtilCreateNetworkMode(c *testing.T, networkMode containertypes.NetworkMode)
 func (s *DockerSuite) TestContainerAPICreateWithCpuSharesCpuset(c *testing.T) {
 func (s *DockerSuite) TestContainerAPICreateWithCpuSharesCpuset(c *testing.T) {
 	// TODO Windows to Windows CI. The CpuShares part could be ported.
 	// TODO Windows to Windows CI. The CpuShares part could be ported.
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 	}
 	}
 
 
-	hostConfig := containertypes.HostConfig{
-		Resources: containertypes.Resources{
+	hostConfig := container.HostConfig{
+		Resources: container.Resources{
 			CPUShares:  512,
 			CPUShares:  512,
 			CpusetCpus: "0",
 			CpusetCpus: "0",
 		},
 		},
@@ -636,7 +636,7 @@ func (s *DockerSuite) TestContainerAPICreateWithCpuSharesCpuset(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "")
+	container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
@@ -913,8 +913,8 @@ func (s *DockerSuite) TestContainerAPIRestart(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	timeout := 1 * time.Second
-	err = cli.ContainerRestart(context.Background(), name, &timeout)
+	timeout := 1
+	err = cli.ContainerRestart(context.Background(), name, container.StopOptions{Timeout: &timeout})
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	assert.Assert(c, waitInspect(name, "{{ .State.Restarting  }} {{ .State.Running  }}", "false true", 15*time.Second) == nil)
 	assert.Assert(c, waitInspect(name, "{{ .State.Restarting  }} {{ .State.Running  }}", "false true", 15*time.Second) == nil)
@@ -930,7 +930,7 @@ func (s *DockerSuite) TestContainerAPIRestartNotimeoutParam(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	err = cli.ContainerRestart(context.Background(), name, nil)
+	err = cli.ContainerRestart(context.Background(), name, container.StopOptions{})
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	assert.Assert(c, waitInspect(name, "{{ .State.Restarting  }} {{ .State.Running  }}", "false true", 15*time.Second) == nil)
 	assert.Assert(c, waitInspect(name, "{{ .State.Restarting  }} {{ .State.Running  }}", "false true", 15*time.Second) == nil)
@@ -938,7 +938,7 @@ func (s *DockerSuite) TestContainerAPIRestartNotimeoutParam(c *testing.T) {
 
 
 func (s *DockerSuite) TestContainerAPIStart(c *testing.T) {
 func (s *DockerSuite) TestContainerAPIStart(c *testing.T) {
 	name := "testing-start"
 	name := "testing-start"
-	config := containertypes.Config{
+	config := container.Config{
 		Image:     "busybox",
 		Image:     "busybox",
 		Cmd:       append([]string{"/bin/sh", "-c"}, sleepCommandForDaemonPlatform()...),
 		Cmd:       append([]string{"/bin/sh", "-c"}, sleepCommandForDaemonPlatform()...),
 		OpenStdin: true,
 		OpenStdin: true,
@@ -948,7 +948,7 @@ func (s *DockerSuite) TestContainerAPIStart(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, name)
+	_, err = cli.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, name)
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	err = cli.ContainerStart(context.Background(), name, types.ContainerStartOptions{})
 	err = cli.ContainerStart(context.Background(), name, types.ContainerStartOptions{})
@@ -965,19 +965,23 @@ func (s *DockerSuite) TestContainerAPIStart(c *testing.T) {
 func (s *DockerSuite) TestContainerAPIStop(c *testing.T) {
 func (s *DockerSuite) TestContainerAPIStop(c *testing.T) {
 	name := "test-api-stop"
 	name := "test-api-stop"
 	runSleepingContainer(c, "-i", "--name", name)
 	runSleepingContainer(c, "-i", "--name", name)
-	timeout := 30 * time.Second
+	timeout := 30
 
 
 	cli, err := client.NewClientWithOpts(client.FromEnv)
 	cli, err := client.NewClientWithOpts(client.FromEnv)
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	err = cli.ContainerStop(context.Background(), name, &timeout)
+	err = cli.ContainerStop(context.Background(), name, container.StopOptions{
+		Timeout: &timeout,
+	})
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	assert.Assert(c, waitInspect(name, "{{ .State.Running  }}", "false", 60*time.Second) == nil)
 	assert.Assert(c, waitInspect(name, "{{ .State.Running  }}", "false", 60*time.Second) == nil)
 
 
 	// second call to start should give 304
 	// second call to start should give 304
 	// maybe add ContainerStartWithRaw to test it
 	// maybe add ContainerStartWithRaw to test it
-	err = cli.ContainerStop(context.Background(), name, &timeout)
+	err = cli.ContainerStop(context.Background(), name, container.StopOptions{
+		Timeout: &timeout,
+	})
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 }
 }
 
 
@@ -1255,14 +1259,14 @@ func (s *DockerSuite) TestContainerAPIPostContainerStop(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	err = cli.ContainerStop(context.Background(), containerID, nil)
+	err = cli.ContainerStop(context.Background(), containerID, container.StopOptions{})
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	assert.Assert(c, waitInspect(containerID, "{{ .State.Running  }}", "false", 60*time.Second) == nil)
 	assert.Assert(c, waitInspect(containerID, "{{ .State.Running  }}", "false", 60*time.Second) == nil)
 }
 }
 
 
 // #14170
 // #14170
 func (s *DockerSuite) TestPostContainerAPICreateWithStringOrSliceEntrypoint(c *testing.T) {
 func (s *DockerSuite) TestPostContainerAPICreateWithStringOrSliceEntrypoint(c *testing.T) {
-	config := containertypes.Config{
+	config := container.Config{
 		Image:      "busybox",
 		Image:      "busybox",
 		Entrypoint: []string{"echo"},
 		Entrypoint: []string{"echo"},
 		Cmd:        []string{"hello", "world"},
 		Cmd:        []string{"hello", "world"},
@@ -1272,7 +1276,7 @@ func (s *DockerSuite) TestPostContainerAPICreateWithStringOrSliceEntrypoint(c *t
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "echotest")
+	_, err = cli.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "echotest")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	out, _ := dockerCmd(c, "start", "-a", "echotest")
 	out, _ := dockerCmd(c, "start", "-a", "echotest")
 	assert.Equal(c, strings.TrimSpace(out), "hello world")
 	assert.Equal(c, strings.TrimSpace(out), "hello world")
@@ -1290,7 +1294,7 @@ func (s *DockerSuite) TestPostContainerAPICreateWithStringOrSliceEntrypoint(c *t
 
 
 // #14170
 // #14170
 func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCmd(c *testing.T) {
 func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCmd(c *testing.T) {
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 		Cmd:   []string{"echo", "hello", "world"},
 		Cmd:   []string{"echo", "hello", "world"},
 	}
 	}
@@ -1299,7 +1303,7 @@ func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCmd(c *testing.T)
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "echotest")
+	_, err = cli.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "echotest")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	out, _ := dockerCmd(c, "start", "-a", "echotest")
 	out, _ := dockerCmd(c, "start", "-a", "echotest")
 	assert.Equal(c, strings.TrimSpace(out), "hello world")
 	assert.Equal(c, strings.TrimSpace(out), "hello world")
@@ -1330,10 +1334,10 @@ func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c *tes
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	assert.Equal(c, res.StatusCode, http.StatusCreated)
 	assert.Equal(c, res.StatusCode, http.StatusCreated)
 
 
-	config2 := containertypes.Config{
+	config2 := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 	}
 	}
-	hostConfig := containertypes.HostConfig{
+	hostConfig := container.HostConfig{
 		CapAdd:  []string{"net_admin", "SYS_ADMIN"},
 		CapAdd:  []string{"net_admin", "SYS_ADMIN"},
 		CapDrop: []string{"SETGID", "CAP_SETPCAP"},
 		CapDrop: []string{"SETGID", "CAP_SETPCAP"},
 	}
 	}
@@ -1342,21 +1346,21 @@ func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c *tes
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config2, &hostConfig, &networktypes.NetworkingConfig{}, nil, "capaddtest1")
+	_, err = cli.ContainerCreate(context.Background(), &config2, &hostConfig, &network.NetworkingConfig{}, nil, "capaddtest1")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 }
 }
 
 
 // #14915
 // #14915
 func (s *DockerSuite) TestContainerAPICreateNoHostConfig118(c *testing.T) {
 func (s *DockerSuite) TestContainerAPICreateNoHostConfig118(c *testing.T) {
 	testRequires(c, DaemonIsLinux) // Windows only support 1.25 or later
 	testRequires(c, DaemonIsLinux) // Windows only support 1.25 or later
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 	}
 	}
 
 
 	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.18"))
 	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.18"))
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
+	_, err = cli.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 }
 }
 
 
@@ -1397,27 +1401,27 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *testing.T
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 	}
 	}
-	hostConfig1 := containertypes.HostConfig{
-		Resources: containertypes.Resources{
+	hostConfig1 := container.HostConfig{
+		Resources: container.Resources{
 			CpusetCpus: "1-42,,",
 			CpusetCpus: "1-42,,",
 		},
 		},
 	}
 	}
 	name := "wrong-cpuset-cpus"
 	name := "wrong-cpuset-cpus"
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig1, &networktypes.NetworkingConfig{}, nil, name)
+	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig1, &network.NetworkingConfig{}, nil, name)
 	expected := "Invalid value 1-42,, for cpuset cpus"
 	expected := "Invalid value 1-42,, for cpuset cpus"
 	assert.ErrorContains(c, err, expected)
 	assert.ErrorContains(c, err, expected)
 
 
-	hostConfig2 := containertypes.HostConfig{
-		Resources: containertypes.Resources{
+	hostConfig2 := container.HostConfig{
+		Resources: container.Resources{
 			CpusetMems: "42-3,1--",
 			CpusetMems: "42-3,1--",
 		},
 		},
 	}
 	}
 	name = "wrong-cpuset-mems"
 	name = "wrong-cpuset-mems"
-	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig2, &networktypes.NetworkingConfig{}, nil, name)
+	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig2, &network.NetworkingConfig{}, nil, name)
 	expected = "Invalid value 42-3,1-- for cpuset mems"
 	expected = "Invalid value 42-3,1-- for cpuset mems"
 	assert.ErrorContains(c, err, expected)
 	assert.ErrorContains(c, err, expected)
 }
 }
@@ -1425,10 +1429,10 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *testing.T
 func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *testing.T) {
 func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *testing.T) {
 	// ShmSize is not supported on Windows
 	// ShmSize is not supported on Windows
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 	}
 	}
-	hostConfig := containertypes.HostConfig{
+	hostConfig := container.HostConfig{
 		ShmSize: -1,
 		ShmSize: -1,
 	}
 	}
 
 
@@ -1436,7 +1440,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "")
+	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
 	assert.ErrorContains(c, err, "SHM size can not be less than 0")
 	assert.ErrorContains(c, err, "SHM size can not be less than 0")
 }
 }
 
 
@@ -1444,7 +1448,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *testin
 	// ShmSize is not supported on Windows
 	// ShmSize is not supported on Windows
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
 
 
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 		Cmd:   []string{"mount"},
 		Cmd:   []string{"mount"},
 	}
 	}
@@ -1453,7 +1457,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *testin
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
+	container, err := cli.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
@@ -1471,7 +1475,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *testin
 func (s *DockerSuite) TestPostContainersCreateShmSizeOmitted(c *testing.T) {
 func (s *DockerSuite) TestPostContainersCreateShmSizeOmitted(c *testing.T) {
 	// ShmSize is not supported on Windows
 	// ShmSize is not supported on Windows
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 		Cmd:   []string{"mount"},
 		Cmd:   []string{"mount"},
 	}
 	}
@@ -1480,7 +1484,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeOmitted(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
+	container, err := cli.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
@@ -1498,12 +1502,12 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeOmitted(c *testing.T) {
 func (s *DockerSuite) TestPostContainersCreateWithShmSize(c *testing.T) {
 func (s *DockerSuite) TestPostContainersCreateWithShmSize(c *testing.T) {
 	// ShmSize is not supported on Windows
 	// ShmSize is not supported on Windows
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 		Cmd:   []string{"mount"},
 		Cmd:   []string{"mount"},
 	}
 	}
 
 
-	hostConfig := containertypes.HostConfig{
+	hostConfig := container.HostConfig{
 		ShmSize: 1073741824,
 		ShmSize: 1073741824,
 	}
 	}
 
 
@@ -1511,7 +1515,7 @@ func (s *DockerSuite) TestPostContainersCreateWithShmSize(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "")
+	container, err := cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
@@ -1529,7 +1533,7 @@ func (s *DockerSuite) TestPostContainersCreateWithShmSize(c *testing.T) {
 func (s *DockerSuite) TestPostContainersCreateMemorySwappinessHostConfigOmitted(c *testing.T) {
 func (s *DockerSuite) TestPostContainersCreateMemorySwappinessHostConfigOmitted(c *testing.T) {
 	// Swappiness is not supported on Windows
 	// Swappiness is not supported on Windows
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 	}
 	}
 
 
@@ -1537,7 +1541,7 @@ func (s *DockerSuite) TestPostContainersCreateMemorySwappinessHostConfigOmitted(
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	container, err := cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, "")
+	container, err := cli.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
 	containerJSON, err := cli.ContainerInspect(context.Background(), container.ID)
@@ -1555,11 +1559,11 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *tes
 	// OomScoreAdj is not supported on Windows
 	// OomScoreAdj is not supported on Windows
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
 
 
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 	}
 	}
 
 
-	hostConfig := containertypes.HostConfig{
+	hostConfig := container.HostConfig{
 		OomScoreAdj: 1001,
 		OomScoreAdj: 1001,
 	}
 	}
 
 
@@ -1568,17 +1572,17 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *tes
 	defer cli.Close()
 	defer cli.Close()
 
 
 	name := "oomscoreadj-over"
 	name := "oomscoreadj-over"
-	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, name)
+	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, name)
 
 
 	expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]"
 	expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]"
 	assert.ErrorContains(c, err, expected)
 	assert.ErrorContains(c, err, expected)
 
 
-	hostConfig = containertypes.HostConfig{
+	hostConfig = container.HostConfig{
 		OomScoreAdj: -1001,
 		OomScoreAdj: -1001,
 	}
 	}
 
 
 	name = "oomscoreadj-low"
 	name = "oomscoreadj-low"
-	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, name)
+	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, name)
 
 
 	expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]"
 	expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]"
 	assert.ErrorContains(c, err, expected)
 	assert.ErrorContains(c, err, expected)
@@ -1600,7 +1604,7 @@ func (s *DockerSuite) TestContainerAPIStatsWithNetworkDisabled(c *testing.T) {
 
 
 	name := "testing-network-disabled"
 	name := "testing-network-disabled"
 
 
-	config := containertypes.Config{
+	config := container.Config{
 		Image:           "busybox",
 		Image:           "busybox",
 		Cmd:             []string{"top"},
 		Cmd:             []string{"top"},
 		NetworkDisabled: true,
 		NetworkDisabled: true,
@@ -1610,7 +1614,7 @@ func (s *DockerSuite) TestContainerAPIStatsWithNetworkDisabled(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, nil, name)
+	_, err = cli.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, name)
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	err = cli.ContainerStart(context.Background(), name, types.ContainerStartOptions{})
 	err = cli.ContainerStart(context.Background(), name, types.ContainerStartOptions{})
@@ -1645,8 +1649,8 @@ func (s *DockerSuite) TestContainerAPIStatsWithNetworkDisabled(c *testing.T) {
 
 
 func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 	type testCase struct {
 	type testCase struct {
-		config     containertypes.Config
-		hostConfig containertypes.HostConfig
+		config     container.Config
+		hostConfig container.HostConfig
 		msg        string
 		msg        string
 	}
 	}
 
 
@@ -1656,11 +1660,11 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 
 
 	cases := []testCase{
 	cases := []testCase{
 		{
 		{
-			config: containertypes.Config{
+			config: container.Config{
 				Image: "busybox",
 				Image: "busybox",
 			},
 			},
-			hostConfig: containertypes.HostConfig{
-				Mounts: []mounttypes.Mount{{
+			hostConfig: container.HostConfig{
+				Mounts: []mount.Mount{{
 					Type:   "notreal",
 					Type:   "notreal",
 					Target: destPath,
 					Target: destPath,
 				},
 				},
@@ -1670,30 +1674,30 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 			msg: "mount type unknown",
 			msg: "mount type unknown",
 		},
 		},
 		{
 		{
-			config: containertypes.Config{
+			config: container.Config{
 				Image: "busybox",
 				Image: "busybox",
 			},
 			},
-			hostConfig: containertypes.HostConfig{
-				Mounts: []mounttypes.Mount{{
+			hostConfig: container.HostConfig{
+				Mounts: []mount.Mount{{
 					Type: "bind"}}},
 					Type: "bind"}}},
 			msg: "Target must not be empty",
 			msg: "Target must not be empty",
 		},
 		},
 		{
 		{
-			config: containertypes.Config{
+			config: container.Config{
 				Image: "busybox",
 				Image: "busybox",
 			},
 			},
-			hostConfig: containertypes.HostConfig{
-				Mounts: []mounttypes.Mount{{
+			hostConfig: container.HostConfig{
+				Mounts: []mount.Mount{{
 					Type:   "bind",
 					Type:   "bind",
 					Target: destPath}}},
 					Target: destPath}}},
 			msg: "Source must not be empty",
 			msg: "Source must not be empty",
 		},
 		},
 		{
 		{
-			config: containertypes.Config{
+			config: container.Config{
 				Image: "busybox",
 				Image: "busybox",
 			},
 			},
-			hostConfig: containertypes.HostConfig{
-				Mounts: []mounttypes.Mount{{
+			hostConfig: container.HostConfig{
+				Mounts: []mount.Mount{{
 					Type:   "bind",
 					Type:   "bind",
 					Source: notExistPath,
 					Source: notExistPath,
 					Target: destPath}}},
 					Target: destPath}}},
@@ -1702,36 +1706,36 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 			// msg: "source path does not exist: " + notExistPath,
 			// msg: "source path does not exist: " + notExistPath,
 		},
 		},
 		{
 		{
-			config: containertypes.Config{
+			config: container.Config{
 				Image: "busybox",
 				Image: "busybox",
 			},
 			},
-			hostConfig: containertypes.HostConfig{
-				Mounts: []mounttypes.Mount{{
+			hostConfig: container.HostConfig{
+				Mounts: []mount.Mount{{
 					Type: "volume"}}},
 					Type: "volume"}}},
 			msg: "Target must not be empty",
 			msg: "Target must not be empty",
 		},
 		},
 		{
 		{
-			config: containertypes.Config{
+			config: container.Config{
 				Image: "busybox",
 				Image: "busybox",
 			},
 			},
-			hostConfig: containertypes.HostConfig{
-				Mounts: []mounttypes.Mount{{
+			hostConfig: container.HostConfig{
+				Mounts: []mount.Mount{{
 					Type:   "volume",
 					Type:   "volume",
 					Source: "hello",
 					Source: "hello",
 					Target: destPath}}},
 					Target: destPath}}},
 			msg: "",
 			msg: "",
 		},
 		},
 		{
 		{
-			config: containertypes.Config{
+			config: container.Config{
 				Image: "busybox",
 				Image: "busybox",
 			},
 			},
-			hostConfig: containertypes.HostConfig{
-				Mounts: []mounttypes.Mount{{
+			hostConfig: container.HostConfig{
+				Mounts: []mount.Mount{{
 					Type:   "volume",
 					Type:   "volume",
 					Source: "hello2",
 					Source: "hello2",
 					Target: destPath,
 					Target: destPath,
-					VolumeOptions: &mounttypes.VolumeOptions{
-						DriverConfig: &mounttypes.Driver{
+					VolumeOptions: &mount.VolumeOptions{
+						DriverConfig: &mount.Driver{
 							Name: "local"}}}}},
 							Name: "local"}}}}},
 			msg: "",
 			msg: "",
 		},
 		},
@@ -1743,26 +1747,26 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 		defer os.RemoveAll(tmpDir)
 		defer os.RemoveAll(tmpDir)
 		cases = append(cases, []testCase{
 		cases = append(cases, []testCase{
 			{
 			{
-				config: containertypes.Config{
+				config: container.Config{
 					Image: "busybox",
 					Image: "busybox",
 				},
 				},
-				hostConfig: containertypes.HostConfig{
-					Mounts: []mounttypes.Mount{{
+				hostConfig: container.HostConfig{
+					Mounts: []mount.Mount{{
 						Type:   "bind",
 						Type:   "bind",
 						Source: tmpDir,
 						Source: tmpDir,
 						Target: destPath}}},
 						Target: destPath}}},
 				msg: "",
 				msg: "",
 			},
 			},
 			{
 			{
-				config: containertypes.Config{
+				config: container.Config{
 					Image: "busybox",
 					Image: "busybox",
 				},
 				},
-				hostConfig: containertypes.HostConfig{
-					Mounts: []mounttypes.Mount{{
+				hostConfig: container.HostConfig{
+					Mounts: []mount.Mount{{
 						Type:          "bind",
 						Type:          "bind",
 						Source:        tmpDir,
 						Source:        tmpDir,
 						Target:        destPath,
 						Target:        destPath,
-						VolumeOptions: &mounttypes.VolumeOptions{}}}},
+						VolumeOptions: &mount.VolumeOptions{}}}},
 				msg: "VolumeOptions must not be specified",
 				msg: "VolumeOptions must not be specified",
 			},
 			},
 		}...)
 		}...)
@@ -1771,17 +1775,17 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 	if DaemonIsWindows() {
 	if DaemonIsWindows() {
 		cases = append(cases, []testCase{
 		cases = append(cases, []testCase{
 			{
 			{
-				config: containertypes.Config{
+				config: container.Config{
 					Image: "busybox",
 					Image: "busybox",
 				},
 				},
-				hostConfig: containertypes.HostConfig{
-					Mounts: []mounttypes.Mount{
+				hostConfig: container.HostConfig{
+					Mounts: []mount.Mount{
 						{
 						{
 							Type:   "volume",
 							Type:   "volume",
 							Source: "not-supported-on-windows",
 							Source: "not-supported-on-windows",
 							Target: destPath,
 							Target: destPath,
-							VolumeOptions: &mounttypes.VolumeOptions{
-								DriverConfig: &mounttypes.Driver{
+							VolumeOptions: &mount.VolumeOptions{
+								DriverConfig: &mount.Driver{
 									Name:    "local",
 									Name:    "local",
 									Options: map[string]string{"type": "tmpfs"},
 									Options: map[string]string{"type": "tmpfs"},
 								},
 								},
@@ -1797,17 +1801,17 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 	if DaemonIsLinux() {
 	if DaemonIsLinux() {
 		cases = append(cases, []testCase{
 		cases = append(cases, []testCase{
 			{
 			{
-				config: containertypes.Config{
+				config: container.Config{
 					Image: "busybox",
 					Image: "busybox",
 				},
 				},
-				hostConfig: containertypes.HostConfig{
-					Mounts: []mounttypes.Mount{
+				hostConfig: container.HostConfig{
+					Mounts: []mount.Mount{
 						{
 						{
 							Type:   "volume",
 							Type:   "volume",
 							Source: "missing-device-opt",
 							Source: "missing-device-opt",
 							Target: destPath,
 							Target: destPath,
-							VolumeOptions: &mounttypes.VolumeOptions{
-								DriverConfig: &mounttypes.Driver{
+							VolumeOptions: &mount.VolumeOptions{
+								DriverConfig: &mount.Driver{
 									Name:    "local",
 									Name:    "local",
 									Options: map[string]string{"foobar": "foobaz"},
 									Options: map[string]string{"foobar": "foobaz"},
 								},
 								},
@@ -1818,17 +1822,17 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 				msg: `invalid option: "foobar"`,
 				msg: `invalid option: "foobar"`,
 			},
 			},
 			{
 			{
-				config: containertypes.Config{
+				config: container.Config{
 					Image: "busybox",
 					Image: "busybox",
 				},
 				},
-				hostConfig: containertypes.HostConfig{
-					Mounts: []mounttypes.Mount{
+				hostConfig: container.HostConfig{
+					Mounts: []mount.Mount{
 						{
 						{
 							Type:   "volume",
 							Type:   "volume",
 							Source: "missing-device-opt",
 							Source: "missing-device-opt",
 							Target: destPath,
 							Target: destPath,
-							VolumeOptions: &mounttypes.VolumeOptions{
-								DriverConfig: &mounttypes.Driver{
+							VolumeOptions: &mount.VolumeOptions{
+								DriverConfig: &mount.Driver{
 									Name:    "local",
 									Name:    "local",
 									Options: map[string]string{"type": "tmpfs"},
 									Options: map[string]string{"type": "tmpfs"},
 								},
 								},
@@ -1839,17 +1843,17 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 				msg: `missing required option: "device"`,
 				msg: `missing required option: "device"`,
 			},
 			},
 			{
 			{
-				config: containertypes.Config{
+				config: container.Config{
 					Image: "busybox",
 					Image: "busybox",
 				},
 				},
-				hostConfig: containertypes.HostConfig{
-					Mounts: []mounttypes.Mount{
+				hostConfig: container.HostConfig{
+					Mounts: []mount.Mount{
 						{
 						{
 							Type:   "volume",
 							Type:   "volume",
 							Source: "missing-type-opt",
 							Source: "missing-type-opt",
 							Target: destPath,
 							Target: destPath,
-							VolumeOptions: &mounttypes.VolumeOptions{
-								DriverConfig: &mounttypes.Driver{
+							VolumeOptions: &mount.VolumeOptions{
+								DriverConfig: &mount.Driver{
 									Name:    "local",
 									Name:    "local",
 									Options: map[string]string{"device": "tmpfs"},
 									Options: map[string]string{"device": "tmpfs"},
 								},
 								},
@@ -1860,17 +1864,17 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 				msg: `missing required option: "type"`,
 				msg: `missing required option: "type"`,
 			},
 			},
 			{
 			{
-				config: containertypes.Config{
+				config: container.Config{
 					Image: "busybox",
 					Image: "busybox",
 				},
 				},
-				hostConfig: containertypes.HostConfig{
-					Mounts: []mounttypes.Mount{
+				hostConfig: container.HostConfig{
+					Mounts: []mount.Mount{
 						{
 						{
 							Type:   "volume",
 							Type:   "volume",
 							Source: "hello4",
 							Source: "hello4",
 							Target: destPath,
 							Target: destPath,
-							VolumeOptions: &mounttypes.VolumeOptions{
-								DriverConfig: &mounttypes.Driver{
+							VolumeOptions: &mount.VolumeOptions{
+								DriverConfig: &mount.Driver{
 									Name:    "local",
 									Name:    "local",
 									Options: map[string]string{"o": "size=1", "type": "tmpfs", "device": "tmpfs"},
 									Options: map[string]string{"o": "size=1", "type": "tmpfs", "device": "tmpfs"},
 								},
 								},
@@ -1881,35 +1885,35 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 				msg: "",
 				msg: "",
 			},
 			},
 			{
 			{
-				config: containertypes.Config{
+				config: container.Config{
 					Image: "busybox",
 					Image: "busybox",
 				},
 				},
-				hostConfig: containertypes.HostConfig{
-					Mounts: []mounttypes.Mount{{
+				hostConfig: container.HostConfig{
+					Mounts: []mount.Mount{{
 						Type:   "tmpfs",
 						Type:   "tmpfs",
 						Target: destPath}}},
 						Target: destPath}}},
 				msg: "",
 				msg: "",
 			},
 			},
 			{
 			{
-				config: containertypes.Config{
+				config: container.Config{
 					Image: "busybox",
 					Image: "busybox",
 				},
 				},
-				hostConfig: containertypes.HostConfig{
-					Mounts: []mounttypes.Mount{{
+				hostConfig: container.HostConfig{
+					Mounts: []mount.Mount{{
 						Type:   "tmpfs",
 						Type:   "tmpfs",
 						Target: destPath,
 						Target: destPath,
-						TmpfsOptions: &mounttypes.TmpfsOptions{
+						TmpfsOptions: &mount.TmpfsOptions{
 							SizeBytes: 4096 * 1024,
 							SizeBytes: 4096 * 1024,
 							Mode:      0700,
 							Mode:      0700,
 						}}}},
 						}}}},
 				msg: "",
 				msg: "",
 			},
 			},
 			{
 			{
-				config: containertypes.Config{
+				config: container.Config{
 					Image: "busybox",
 					Image: "busybox",
 				},
 				},
-				hostConfig: containertypes.HostConfig{
-					Mounts: []mounttypes.Mount{{
+				hostConfig: container.HostConfig{
+					Mounts: []mount.Mount{{
 						Type:   "tmpfs",
 						Type:   "tmpfs",
 						Source: "/shouldnotbespecified",
 						Source: "/shouldnotbespecified",
 						Target: destPath}}},
 						Target: destPath}}},
@@ -1926,7 +1930,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *testing.T) {
 	for i, x := range cases {
 	for i, x := range cases {
 		x := x
 		x := x
 		c.Run(fmt.Sprintf("case %d", i), func(c *testing.T) {
 		c.Run(fmt.Sprintf("case %d", i), func(c *testing.T) {
-			_, err = apiClient.ContainerCreate(context.Background(), &x.config, &x.hostConfig, &networktypes.NetworkingConfig{}, nil, "")
+			_, err = apiClient.ContainerCreate(context.Background(), &x.config, &x.hostConfig, &network.NetworkingConfig{}, nil, "")
 			if len(x.msg) > 0 {
 			if len(x.msg) > 0 {
 				assert.ErrorContains(c, err, x.msg, "%v", cases[i].config)
 				assert.ErrorContains(c, err, x.msg, "%v", cases[i].config)
 			} else {
 			} else {
@@ -1946,12 +1950,12 @@ func (s *DockerSuite) TestContainerAPICreateMountsBindRead(c *testing.T) {
 	defer os.RemoveAll(tmpDir)
 	defer os.RemoveAll(tmpDir)
 	err = os.WriteFile(filepath.Join(tmpDir, "bar"), []byte("hello"), 0666)
 	err = os.WriteFile(filepath.Join(tmpDir, "bar"), []byte("hello"), 0666)
 	assert.NilError(c, err)
 	assert.NilError(c, err)
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 		Cmd:   []string{"/bin/sh", "-c", "cat /foo/bar"},
 		Cmd:   []string{"/bin/sh", "-c", "cat /foo/bar"},
 	}
 	}
-	hostConfig := containertypes.HostConfig{
-		Mounts: []mounttypes.Mount{
+	hostConfig := container.HostConfig{
+		Mounts: []mount.Mount{
 			{Type: "bind", Source: tmpDir, Target: destPath},
 			{Type: "bind", Source: tmpDir, Target: destPath},
 		},
 		},
 	}
 	}
@@ -1959,7 +1963,7 @@ func (s *DockerSuite) TestContainerAPICreateMountsBindRead(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, "test")
+	_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "test")
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 
 
 	out, _ := dockerCmd(c, "start", "-a", "test")
 	out, _ := dockerCmd(c, "start", "-a", "test")
@@ -1986,7 +1990,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *testing.T) {
 	}
 	}
 
 
 	type testCase struct {
 	type testCase struct {
-		spec     mounttypes.Mount
+		spec     mount.Mount
 		expected types.MountPoint
 		expected types.MountPoint
 	}
 	}
 
 
@@ -2004,23 +2008,23 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *testing.T) {
 		// use literal strings here for `Type` instead of the defined constants in the volume package to keep this honest
 		// use literal strings here for `Type` instead of the defined constants in the volume package to keep this honest
 		// Validation of the actual `Mount` struct is done in another test is not needed here
 		// Validation of the actual `Mount` struct is done in another test is not needed here
 		{
 		{
-			spec:     mounttypes.Mount{Type: "volume", Target: destPath},
+			spec:     mount.Mount{Type: "volume", Target: destPath},
 			expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 			expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 		},
 		},
 		{
 		{
-			spec:     mounttypes.Mount{Type: "volume", Target: destPath + slash},
+			spec:     mount.Mount{Type: "volume", Target: destPath + slash},
 			expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 			expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 		},
 		},
 		{
 		{
-			spec:     mounttypes.Mount{Type: "volume", Target: destPath, Source: "test1"},
+			spec:     mount.Mount{Type: "volume", Target: destPath, Source: "test1"},
 			expected: types.MountPoint{Type: "volume", Name: "test1", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 			expected: types.MountPoint{Type: "volume", Name: "test1", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 		},
 		},
 		{
 		{
-			spec:     mounttypes.Mount{Type: "volume", Target: destPath, ReadOnly: true, Source: "test2"},
+			spec:     mount.Mount{Type: "volume", Target: destPath, ReadOnly: true, Source: "test2"},
 			expected: types.MountPoint{Type: "volume", Name: "test2", RW: false, Destination: destPath, Mode: selinuxSharedLabel},
 			expected: types.MountPoint{Type: "volume", Name: "test2", RW: false, Destination: destPath, Mode: selinuxSharedLabel},
 		},
 		},
 		{
 		{
-			spec:     mounttypes.Mount{Type: "volume", Target: destPath, Source: "test3", VolumeOptions: &mounttypes.VolumeOptions{DriverConfig: &mounttypes.Driver{Name: volume.DefaultDriverName}}},
+			spec:     mount.Mount{Type: "volume", Target: destPath, Source: "test3", VolumeOptions: &mount.VolumeOptions{DriverConfig: &mount.Driver{Name: volume.DefaultDriverName}}},
 			expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", Name: "test3", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 			expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", Name: "test3", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 		},
 		},
 	}
 	}
@@ -2032,7 +2036,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *testing.T) {
 		defer os.RemoveAll(tmpDir1)
 		defer os.RemoveAll(tmpDir1)
 		cases = append(cases, []testCase{
 		cases = append(cases, []testCase{
 			{
 			{
-				spec: mounttypes.Mount{
+				spec: mount.Mount{
 					Type:   "bind",
 					Type:   "bind",
 					Source: tmpDir1,
 					Source: tmpDir1,
 					Target: destPath,
 					Target: destPath,
@@ -2045,7 +2049,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *testing.T) {
 				},
 				},
 			},
 			},
 			{
 			{
-				spec:     mounttypes.Mount{Type: "bind", Source: tmpDir1, Target: destPath, ReadOnly: true},
+				spec:     mount.Mount{Type: "bind", Source: tmpDir1, Target: destPath, ReadOnly: true},
 				expected: types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir1},
 				expected: types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir1},
 			},
 			},
 		}...)
 		}...)
@@ -2060,15 +2064,15 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *testing.T) {
 
 
 			cases = append(cases, []testCase{
 			cases = append(cases, []testCase{
 				{
 				{
-					spec:     mounttypes.Mount{Type: "bind", Source: tmpDir3, Target: destPath},
+					spec:     mount.Mount{Type: "bind", Source: tmpDir3, Target: destPath},
 					expected: types.MountPoint{Type: "bind", RW: true, Destination: destPath, Source: tmpDir3},
 					expected: types.MountPoint{Type: "bind", RW: true, Destination: destPath, Source: tmpDir3},
 				},
 				},
 				{
 				{
-					spec:     mounttypes.Mount{Type: "bind", Source: tmpDir3, Target: destPath, ReadOnly: true},
+					spec:     mount.Mount{Type: "bind", Source: tmpDir3, Target: destPath, ReadOnly: true},
 					expected: types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir3},
 					expected: types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir3},
 				},
 				},
 				{
 				{
-					spec:     mounttypes.Mount{Type: "bind", Source: tmpDir3, Target: destPath, ReadOnly: true, BindOptions: &mounttypes.BindOptions{Propagation: "shared"}},
+					spec:     mount.Mount{Type: "bind", Source: tmpDir3, Target: destPath, ReadOnly: true, BindOptions: &mount.BindOptions{Propagation: "shared"}},
 					expected: types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir3, Propagation: "shared"},
 					expected: types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir3, Propagation: "shared"},
 				},
 				},
 			}...)
 			}...)
@@ -2078,19 +2082,19 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *testing.T) {
 	if testEnv.OSType != "windows" { // Windows does not support volume populate
 	if testEnv.OSType != "windows" { // Windows does not support volume populate
 		cases = append(cases, []testCase{
 		cases = append(cases, []testCase{
 			{
 			{
-				spec:     mounttypes.Mount{Type: "volume", Target: destPath, VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}},
+				spec:     mount.Mount{Type: "volume", Target: destPath, VolumeOptions: &mount.VolumeOptions{NoCopy: true}},
 				expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 				expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 			},
 			},
 			{
 			{
-				spec:     mounttypes.Mount{Type: "volume", Target: destPath + slash, VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}},
+				spec:     mount.Mount{Type: "volume", Target: destPath + slash, VolumeOptions: &mount.VolumeOptions{NoCopy: true}},
 				expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 				expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 			},
 			},
 			{
 			{
-				spec:     mounttypes.Mount{Type: "volume", Target: destPath, Source: "test4", VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}},
+				spec:     mount.Mount{Type: "volume", Target: destPath, Source: "test4", VolumeOptions: &mount.VolumeOptions{NoCopy: true}},
 				expected: types.MountPoint{Type: "volume", Name: "test4", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 				expected: types.MountPoint{Type: "volume", Name: "test4", RW: true, Destination: destPath, Mode: selinuxSharedLabel},
 			},
 			},
 			{
 			{
-				spec:     mounttypes.Mount{Type: "volume", Target: destPath, Source: "test5", ReadOnly: true, VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}},
+				spec:     mount.Mount{Type: "volume", Target: destPath, Source: "test5", ReadOnly: true, VolumeOptions: &mount.VolumeOptions{NoCopy: true}},
 				expected: types.MountPoint{Type: "volume", Name: "test5", RW: false, Destination: destPath, Mode: selinuxSharedLabel},
 				expected: types.MountPoint{Type: "volume", Name: "test5", RW: false, Destination: destPath, Mode: selinuxSharedLabel},
 			},
 			},
 		}...)
 		}...)
@@ -2103,9 +2107,9 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *testing.T) {
 		c.Run(fmt.Sprintf("%d config: %v", i, x.spec), func(c *testing.T) {
 		c.Run(fmt.Sprintf("%d config: %v", i, x.spec), func(c *testing.T) {
 			container, err := apiclient.ContainerCreate(
 			container, err := apiclient.ContainerCreate(
 				ctx,
 				ctx,
-				&containertypes.Config{Image: testImg},
-				&containertypes.HostConfig{Mounts: []mounttypes.Mount{x.spec}},
-				&networktypes.NetworkingConfig{},
+				&container.Config{Image: testImg},
+				&container.HostConfig{Mounts: []mount.Mount{x.spec}},
+				&network.NetworkingConfig{},
 				nil,
 				nil,
 				"")
 				"")
 			assert.NilError(c, err)
 			assert.NilError(c, err)
@@ -2179,22 +2183,22 @@ func containerExit(apiclient client.APIClient, name string) func(poll.LogT) poll
 func (s *DockerSuite) TestContainersAPICreateMountsTmpfs(c *testing.T) {
 func (s *DockerSuite) TestContainersAPICreateMountsTmpfs(c *testing.T) {
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
 	type testCase struct {
 	type testCase struct {
-		cfg             mounttypes.Mount
+		cfg             mount.Mount
 		expectedOptions []string
 		expectedOptions []string
 	}
 	}
 	target := "/foo"
 	target := "/foo"
 	cases := []testCase{
 	cases := []testCase{
 		{
 		{
-			cfg: mounttypes.Mount{
+			cfg: mount.Mount{
 				Type:   "tmpfs",
 				Type:   "tmpfs",
 				Target: target},
 				Target: target},
 			expectedOptions: []string{"rw", "nosuid", "nodev", "noexec", "relatime"},
 			expectedOptions: []string{"rw", "nosuid", "nodev", "noexec", "relatime"},
 		},
 		},
 		{
 		{
-			cfg: mounttypes.Mount{
+			cfg: mount.Mount{
 				Type:   "tmpfs",
 				Type:   "tmpfs",
 				Target: target,
 				Target: target,
-				TmpfsOptions: &mounttypes.TmpfsOptions{
+				TmpfsOptions: &mount.TmpfsOptions{
 					SizeBytes: 4096 * 1024, Mode: 0700}},
 					SizeBytes: 4096 * 1024, Mode: 0700}},
 			expectedOptions: []string{"rw", "nosuid", "nodev", "noexec", "relatime", "size=4096k", "mode=700"},
 			expectedOptions: []string{"rw", "nosuid", "nodev", "noexec", "relatime", "size=4096k", "mode=700"},
 		},
 		},
@@ -2204,17 +2208,17 @@ func (s *DockerSuite) TestContainersAPICreateMountsTmpfs(c *testing.T) {
 	assert.NilError(c, err)
 	assert.NilError(c, err)
 	defer cli.Close()
 	defer cli.Close()
 
 
-	config := containertypes.Config{
+	config := container.Config{
 		Image: "busybox",
 		Image: "busybox",
 		Cmd:   []string{"/bin/sh", "-c", fmt.Sprintf("mount | grep 'tmpfs on %s'", target)},
 		Cmd:   []string{"/bin/sh", "-c", fmt.Sprintf("mount | grep 'tmpfs on %s'", target)},
 	}
 	}
 	for i, x := range cases {
 	for i, x := range cases {
 		cName := fmt.Sprintf("test-tmpfs-%d", i)
 		cName := fmt.Sprintf("test-tmpfs-%d", i)
-		hostConfig := containertypes.HostConfig{
-			Mounts: []mounttypes.Mount{x.cfg},
+		hostConfig := container.HostConfig{
+			Mounts: []mount.Mount{x.cfg},
 		}
 		}
 
 
-		_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &networktypes.NetworkingConfig{}, nil, cName)
+		_, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, cName)
 		assert.NilError(c, err)
 		assert.NilError(c, err)
 		out, _ := dockerCmd(c, "start", "-a", cName)
 		out, _ := dockerCmd(c, "start", "-a", cName)
 		for _, option := range x.expectedOptions {
 		for _, option := range x.expectedOptions {

+ 2 - 1
integration/container/pause_test.go

@@ -8,6 +8,7 @@ import (
 
 
 	containerderrdefs "github.com/containerd/containerd/errdefs"
 	containerderrdefs "github.com/containerd/containerd/errdefs"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
+	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/events"
 	"github.com/docker/docker/api/types/events"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/versions"
 	"github.com/docker/docker/api/types/versions"
@@ -80,7 +81,7 @@ func TestPauseStopPausedContainer(t *testing.T) {
 	err := client.ContainerPause(ctx, cID)
 	err := client.ContainerPause(ctx, cID)
 	assert.NilError(t, err)
 	assert.NilError(t, err)
 
 
-	err = client.ContainerStop(ctx, cID, nil)
+	err = client.ContainerStop(ctx, cID, containertypes.StopOptions{})
 	assert.NilError(t, err)
 	assert.NilError(t, err)
 
 
 	poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
 	poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))

+ 1 - 1
integration/container/rename_test.go

@@ -143,7 +143,7 @@ func TestRenameAnonymousContainer(t *testing.T) {
 	assert.NilError(t, err)
 	assert.NilError(t, err)
 	// Stop/Start the container to get registered
 	// Stop/Start the container to get registered
 	// FIXME(vdemeester) this is a really weird behavior as it fails otherwise
 	// FIXME(vdemeester) this is a really weird behavior as it fails otherwise
-	err = client.ContainerStop(ctx, container1Name, nil)
+	err = client.ContainerStop(ctx, container1Name, containertypes.StopOptions{})
 	assert.NilError(t, err)
 	assert.NilError(t, err)
 	err = client.ContainerStart(ctx, container1Name, types.ContainerStartOptions{})
 	err = client.ContainerStart(ctx, container1Name, types.ContainerStartOptions{})
 	assert.NilError(t, err)
 	assert.NilError(t, err)

+ 2 - 2
integration/container/stop_linux_test.go

@@ -9,6 +9,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
+	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/integration/internal/container"
 	"github.com/docker/docker/integration/internal/container"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/icmd"
 	"gotest.tools/v3/icmd"
@@ -56,8 +57,7 @@ func TestStopContainerWithTimeout(t *testing.T) {
 			t.Parallel()
 			t.Parallel()
 			id := container.Run(ctx, t, client, testCmd)
 			id := container.Run(ctx, t, client, testCmd)
 
 
-			timeout := time.Duration(d.timeout) * time.Second
-			err := client.ContainerStop(ctx, id, &timeout)
+			err := client.ContainerStop(ctx, id, containertypes.StopOptions{Timeout: &d.timeout})
 			assert.NilError(t, err)
 			assert.NilError(t, err)
 
 
 			poll.WaitOn(t, container.IsStopped(ctx, client, id),
 			poll.WaitOn(t, container.IsStopped(ctx, client, id),

+ 2 - 1
integration/container/stop_test.go

@@ -5,6 +5,7 @@ import (
 	"testing"
 	"testing"
 	"time"
 	"time"
 
 
+	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/integration/internal/container"
 	"github.com/docker/docker/integration/internal/container"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/poll"
 	"gotest.tools/v3/poll"
@@ -29,7 +30,7 @@ func TestStopContainerWithRestartPolicyAlways(t *testing.T) {
 	}
 	}
 
 
 	for _, name := range names {
 	for _, name := range names {
-		err := client.ContainerStop(ctx, name, nil)
+		err := client.ContainerStop(ctx, name, containertypes.StopOptions{})
 		assert.NilError(t, err)
 		assert.NilError(t, err)
 	}
 	}
 
 

+ 2 - 2
integration/container/stop_windows_test.go

@@ -6,6 +6,7 @@ import (
 	"testing"
 	"testing"
 	"time"
 	"time"
 
 
+	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/integration/internal/container"
 	"github.com/docker/docker/integration/internal/container"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/poll"
 	"gotest.tools/v3/poll"
@@ -53,8 +54,7 @@ func TestStopContainerWithTimeout(t *testing.T) {
 			t.Parallel()
 			t.Parallel()
 			id := container.Run(ctx, t, client, testCmd)
 			id := container.Run(ctx, t, client, testCmd)
 
 
-			timeout := time.Duration(d.timeout) * time.Second
-			err := client.ContainerStop(ctx, id, &timeout)
+			err := client.ContainerStop(ctx, id, containertypes.StopOptions{Timeout: &d.timeout})
 			assert.NilError(t, err)
 			assert.NilError(t, err)
 
 
 			poll.WaitOn(t, container.IsStopped(ctx, client, id),
 			poll.WaitOn(t, container.IsStopped(ctx, client, id),

+ 2 - 1
integration/container/wait_test.go

@@ -5,6 +5,7 @@ import (
 	"testing"
 	"testing"
 	"time"
 	"time"
 
 
+	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/integration/internal/container"
 	"github.com/docker/docker/integration/internal/container"
 	"github.com/docker/docker/testutil/request"
 	"github.com/docker/docker/testutil/request"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert"
@@ -86,7 +87,7 @@ func TestWaitBlocked(t *testing.T) {
 
 
 			waitResC, errC := cli.ContainerWait(ctx, containerID, "")
 			waitResC, errC := cli.ContainerWait(ctx, containerID, "")
 
 
-			err := cli.ContainerStop(ctx, containerID, nil)
+			err := cli.ContainerStop(ctx, containerID, containertypes.StopOptions{})
 			assert.NilError(t, err)
 			assert.NilError(t, err)
 
 
 			select {
 			select {