diff --git a/components/engine/daemon/container.go b/components/engine/daemon/container.go index 1c01a74ed6..a16abf2144 100644 --- a/components/engine/daemon/container.go +++ b/components/engine/daemon/container.go @@ -343,6 +343,16 @@ func (daemon *Daemon) verifyContainerSettings(platform string, hostConfig *conta return nil, errors.Errorf("invalid isolation '%s' on %s", hostConfig.Isolation, runtime.GOOS) } + var ( + err error + warnings []string + ) // Now do platform-specific verification - return verifyPlatformContainerSettings(daemon, hostConfig, config, update) + if warnings, err = verifyPlatformContainerSettings(daemon, hostConfig, config, update); err != nil { + return warnings, err + } + if hostConfig.NetworkMode.IsHost() && len(hostConfig.PortBindings) > 0 { + warnings = append(warnings, "Published ports are discarded when using host network mode") + } + return warnings, err } diff --git a/components/engine/daemon/container_unix_test.go b/components/engine/daemon/container_unix_test.go new file mode 100644 index 0000000000..e102be6cdc --- /dev/null +++ b/components/engine/daemon/container_unix_test.go @@ -0,0 +1,44 @@ +// +build linux freebsd + +package daemon + +import ( + "testing" + + "github.com/docker/docker/api/types" + containertypes "github.com/docker/docker/api/types/container" + "github.com/docker/docker/daemon/config" + "github.com/docker/go-connections/nat" + "github.com/stretchr/testify/require" +) + +// TestContainerWarningHostAndPublishPorts that a warning is returned when setting network mode to host and specifying published ports. +// This should not be tested on Windows because Windows doesn't support "host" network mode. +func TestContainerWarningHostAndPublishPorts(t *testing.T) { + testCases := []struct { + ports nat.PortMap + warnings []string + }{ + {ports: nat.PortMap{}}, + {ports: nat.PortMap{ + "8080": []nat.PortBinding{{HostPort: "8989"}}, + }, warnings: []string{"Published ports are discarded when using host network mode"}}, + } + + for _, tc := range testCases { + hostConfig := &containertypes.HostConfig{ + Runtime: "runc", + NetworkMode: "host", + PortBindings: tc.ports, + } + cs := &config.Config{ + CommonUnixConfig: config.CommonUnixConfig{ + Runtimes: map[string]types.Runtime{"runc": {}}, + }, + } + d := &Daemon{configStore: cs} + wrns, err := d.verifyContainerSettings("", hostConfig, &containertypes.Config{}, false) + require.NoError(t, err) + require.Equal(t, tc.warnings, wrns) + } +} diff --git a/components/engine/integration/build/build_test.go b/components/engine/integration/build/build_test.go index 2a87204113..3f7b1dcf34 100644 --- a/components/engine/integration/build/build_test.go +++ b/components/engine/integration/build/build_test.go @@ -244,6 +244,75 @@ RUN cat somefile` assert.Contains(t, image.Config.Env, "bar=baz") } +// #35403 #36122 +func TestBuildUncleanTarFilenames(t *testing.T) { + ctx := context.TODO() + defer setupTest(t)() + + dockerfile := `FROM scratch +COPY foo / +FROM scratch +COPY bar /` + + buf := bytes.NewBuffer(nil) + w := tar.NewWriter(buf) + writeTarRecord(t, w, "Dockerfile", dockerfile) + writeTarRecord(t, w, "../foo", "foocontents0") + writeTarRecord(t, w, "/bar", "barcontents0") + err := w.Close() + require.NoError(t, err) + + apiclient := testEnv.APIClient() + resp, err := apiclient.ImageBuild(ctx, + buf, + types.ImageBuildOptions{ + Remove: true, + ForceRemove: true, + }) + + out := bytes.NewBuffer(nil) + require.NoError(t, err) + _, err = io.Copy(out, resp.Body) + resp.Body.Close() + require.NoError(t, err) + + // repeat with changed data should not cause cache hits + + buf = bytes.NewBuffer(nil) + w = tar.NewWriter(buf) + writeTarRecord(t, w, "Dockerfile", dockerfile) + writeTarRecord(t, w, "../foo", "foocontents1") + writeTarRecord(t, w, "/bar", "barcontents1") + err = w.Close() + require.NoError(t, err) + + resp, err = apiclient.ImageBuild(ctx, + buf, + types.ImageBuildOptions{ + Remove: true, + ForceRemove: true, + }) + + out = bytes.NewBuffer(nil) + require.NoError(t, err) + _, err = io.Copy(out, resp.Body) + resp.Body.Close() + require.NoError(t, err) + require.NotContains(t, out.String(), "Using cache") +} + +func writeTarRecord(t *testing.T, w *tar.Writer, fn, contents string) { + err := w.WriteHeader(&tar.Header{ + Name: fn, + Mode: 0600, + Size: int64(len(contents)), + Typeflag: '0', + }) + require.NoError(t, err) + _, err = w.Write([]byte(contents)) + require.NoError(t, err) +} + type buildLine struct { Stream string Aux struct { diff --git a/components/engine/pkg/tarsum/tarsum.go b/components/engine/pkg/tarsum/tarsum.go index 6ad152a2ed..8c8478a455 100644 --- a/components/engine/pkg/tarsum/tarsum.go +++ b/components/engine/pkg/tarsum/tarsum.go @@ -236,7 +236,7 @@ func (ts *tarSum) Read(buf []byte) (int, error) { } return n, err } - ts.currentFile = path.Clean(currentHeader.Name) + ts.currentFile = path.Join(".", path.Join("/", currentHeader.Name)) if err := ts.encodeHeader(currentHeader); err != nil { return 0, err }