Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0be687a
cli/command/container: don't set CopyToContainerOptions.AllowOverwrit…
thaJeztah Jul 13, 2025
50fa436
Dockerfile: update compose to v2.38.2
thaJeztah Jul 13, 2025
e6b8cc1
Dockerfile: update buildx to v0.25.0
thaJeztah Jul 13, 2025
1264a59
Dockerfile: bump gotest.tools/gotestsum v1.12.3 (for go1.25)
thaJeztah Jul 13, 2025
e0f4bc6
cli/command/formatter: add TrunateID utility
thaJeztah Jul 14, 2025
9b047a5
remove uses of pkg/stringid.GenerateRandomID()
thaJeztah Jul 14, 2025
3600ebc
remove uses of github.com/docker/docker/pkg/ioutils ReadCloserWrapper
thaJeztah Jul 14, 2025
53d02ec
remove use of github.com/docker/docker/pkg/longpath
thaJeztah Jul 14, 2025
7668b68
Merge pull request #6176 from thaJeztah/rm_use_AllowOverwriteDirWithFile
thaJeztah Jul 14, 2025
0f2b709
cli/command/container: diff: remove redundant validation and cleanup
thaJeztah Jul 14, 2025
7d574b8
Merge pull request #6180 from thaJeztah/truncate_id
thaJeztah Jul 15, 2025
8b6436e
Dockerfile: document ALPINE_VERSION build-arg
thaJeztah Jul 16, 2025
d7181e4
Merge pull request #6185 from thaJeztah/alpine_doc
thaJeztah Jul 16, 2025
143f361
Merge pull request #6179 from thaJeztah/bump_gotestsum
thaJeztah Jul 16, 2025
f5f3b02
Merge pull request #6178 from thaJeztah/bump_dev_tools
thaJeztah Jul 16, 2025
3d98579
cli/command: remove some redundant import-aliases
thaJeztah Jul 13, 2025
ea2a0c3
Merge pull request #6177 from thaJeztah/rm_aliases
thaJeztah Jul 16, 2025
bc01f84
Merge pull request #6182 from thaJeztah/fork_longpath
thaJeztah Jul 16, 2025
9c25614
Merge pull request #6181 from thaJeztah/fork_readCloserWrapper
thaJeztah Jul 16, 2025
980b856
Merge pull request #6183 from thaJeztah/diff_simplify
thaJeztah Jul 16, 2025
b82e19e
[28.x] merge v28.3.3 tag into v28.x
thaJeztah Aug 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
# syntax=docker/dockerfile:1

ARG BASE_VARIANT=alpine

# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image.
# It must be a supported tag in the docker.io/library/alpine image repository
# that's also available as alpine image variant for the Golang version used.
ARG ALPINE_VERSION=3.21
ARG BASE_DEBIAN_DISTRO=bookworm

ARG GO_VERSION=1.24.5
ARG XX_VERSION=1.6.1
ARG GOVERSIONINFO_VERSION=v1.4.1
ARG GOTESTSUM_VERSION=v1.12.0

# GOTESTSUM_VERSION sets the version of gotestsum to install in the dev container.
# It must be a valid tag in the https://github.com/gotestyourself/gotestsum repository.
ARG GOTESTSUM_VERSION=v1.12.3

# BUILDX_VERSION sets the version of buildx to use for the e2e tests.
# It must be a tag in the docker.io/docker/buildx-bin image repository
# on Docker Hub.
ARG BUILDX_VERSION=0.24.0
ARG COMPOSE_VERSION=v2.36.2
ARG BUILDX_VERSION=0.25.0

# COMPOSE_VERSION is the version of compose to install in the dev container.
# It must be a tag in the docker.io/docker/compose-bin image repository
# on Docker Hub.
ARG COMPOSE_VERSION=v2.38.2

FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx

Expand Down
2 changes: 1 addition & 1 deletion cli/command/config/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/cli/command/inspect"
"github.com/docker/docker/api/types/swarm"
units "github.com/docker/go-units"
"github.com/docker/go-units"
)

const (
Expand Down
5 changes: 2 additions & 3 deletions cli/command/container/cp.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/streams"
"github.com/docker/docker/api/types/container"
units "github.com/docker/go-units"
"github.com/docker/go-units"
"github.com/moby/go-archive"
"github.com/morikuni/aec"
"github.com/pkg/errors"
Expand Down Expand Up @@ -398,8 +398,7 @@ func copyToContainer(ctx context.Context, dockerCLI command.Cli, copyConfig cpCo
}

options := container.CopyToContainerOptions{
AllowOverwriteDirWithFile: false,
CopyUIDGID: copyConfig.copyUIDGID,
CopyUIDGID: copyConfig.copyUIDGID,
}

if copyConfig.quiet {
Expand Down
19 changes: 4 additions & 15 deletions cli/command/container/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,17 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/command/formatter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

type diffOptions struct {
container string
}

// NewDiffCommand creates a new cobra.Command for `docker diff`
func NewDiffCommand(dockerCli command.Cli) *cobra.Command {
var opts diffOptions

return &cobra.Command{
Use: "diff CONTAINER",
Short: "Inspect changes to files or directories on a container's filesystem",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.container = args[0]
return runDiff(cmd.Context(), dockerCli, &opts)
return runDiff(cmd.Context(), dockerCli, args[0])
},
Annotations: map[string]string{
"aliases": "docker container diff, docker diff",
Expand All @@ -34,16 +26,13 @@ func NewDiffCommand(dockerCli command.Cli) *cobra.Command {
}
}

func runDiff(ctx context.Context, dockerCli command.Cli, opts *diffOptions) error {
if opts.container == "" {
return errors.New("Container name cannot be empty")
}
changes, err := dockerCli.Client().ContainerDiff(ctx, opts.container)
func runDiff(ctx context.Context, dockerCLI command.Cli, containerID string) error {
changes, err := dockerCLI.Client().ContainerDiff(ctx, containerID)
if err != nil {
return err
}
diffCtx := formatter.Context{
Output: dockerCli.Out(),
Output: dockerCLI.Out(),
Format: NewDiffFormat("{{.Type}} {{.Path}}"),
}
return DiffFormatWrite(diffCtx, changes)
Expand Down
14 changes: 0 additions & 14 deletions cli/command/container/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,3 @@ func TestRunDiffClientError(t *testing.T) {
err := cmd.Execute()
assert.ErrorIs(t, err, clientError)
}

func TestRunDiffEmptyContainerError(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})

cmd := NewDiffCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)

containerID := ""
cmd.SetArgs([]string{containerID})

err := cmd.Execute()
assert.Error(t, err, "Container name cannot be empty")
}
5 changes: 2 additions & 3 deletions cli/command/container/formatter_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import (
"sync"

"github.com/docker/cli/cli/command/formatter"
"github.com/docker/docker/pkg/stringid"
units "github.com/docker/go-units"
"github.com/docker/go-units"
)

const (
Expand Down Expand Up @@ -176,7 +175,7 @@ func (c *statsContext) Name() string {

func (c *statsContext) ID() string {
if c.trunc {
return stringid.TruncateID(c.s.ID)
return formatter.TruncateID(c.s.ID)
}
return c.s.ID
}
Expand Down
4 changes: 2 additions & 2 deletions cli/command/container/formatter_stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import (
"testing"

"github.com/docker/cli/cli/command/formatter"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/cli/internal/test"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)

func TestContainerStatsContext(t *testing.T) {
containerID := stringid.GenerateRandomID()
containerID := test.RandomID()

var ctx statsContext
tt := []struct {
Expand Down
18 changes: 16 additions & 2 deletions cli/command/container/hijack.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"github.com/docker/cli/cli/command"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/stdcopy"
"github.com/moby/term"
"github.com/sirupsen/logrus"
Expand All @@ -19,6 +18,18 @@ import (
// TODO: This could be moved to `pkg/term`.
var defaultEscapeKeys = []byte{16, 17}

// readCloserWrapper wraps an io.Reader, and implements an io.ReadCloser
// It calls the given callback function when closed.
type readCloserWrapper struct {
io.Reader
closer func() error
}

// Close calls back the passed closer function
func (r *readCloserWrapper) Close() error {
return r.closer()
}

// A hijackedIOStreamer handles copying input to and output from streams to the
// connection.
type hijackedIOStreamer struct {
Expand Down Expand Up @@ -100,7 +111,10 @@ func (h *hijackedIOStreamer) setupInput() (restore func(), err error) {
}
}

h.inputStream = ioutils.NewReadCloserWrapper(term.NewEscapeProxy(h.inputStream, escapeKeys), h.inputStream.Close)
h.inputStream = &readCloserWrapper{
Reader: term.NewEscapeProxy(h.inputStream, escapeKeys),
closer: h.inputStream.Close,
}

return restore, nil
}
Expand Down
2 changes: 1 addition & 1 deletion cli/command/container/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/internal/prompt"
"github.com/docker/cli/opts"
units "github.com/docker/go-units"
"github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
Expand Down
5 changes: 2 additions & 3 deletions cli/command/formatter/buildcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"time"

"github.com/docker/docker/api/types/build"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/go-units"
)

Expand Down Expand Up @@ -115,7 +114,7 @@ func (c *buildCacheContext) MarshalJSON() ([]byte, error) {
func (c *buildCacheContext) ID() string {
id := c.v.ID
if c.trunc {
id = stringid.TruncateID(c.v.ID)
id = TruncateID(c.v.ID)
}
if c.v.InUse {
return id + "*"
Expand All @@ -131,7 +130,7 @@ func (c *buildCacheContext) Parent() string {
parent = c.v.Parent //nolint:staticcheck // Ignore SA1019: Field was deprecated in API v1.42, but kept for backward compatibility
}
if c.trunc {
return stringid.TruncateID(parent)
return TruncateID(parent)
}
return parent
}
Expand Down
5 changes: 2 additions & 3 deletions cli/command/formatter/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/containerd/platforms"
"github.com/distribution/reference"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/go-units"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
Expand Down Expand Up @@ -135,7 +134,7 @@ func (c *ContainerContext) MarshalJSON() ([]byte, error) {
// option being set, the full or truncated ID is returned.
func (c *ContainerContext) ID() string {
if c.trunc {
return stringid.TruncateID(c.c.ID)
return TruncateID(c.c.ID)
}
return c.c.ID
}
Expand Down Expand Up @@ -172,7 +171,7 @@ func (c *ContainerContext) Image() string {
return "<no image>"
}
if c.trunc {
if trunc := stringid.TruncateID(c.c.ImageID); trunc == stringid.TruncateID(c.c.Image) {
if trunc := TruncateID(c.c.ImageID); trunc == TruncateID(c.c.Image) {
return trunc
}
// truncate digest if no-trunc option was not selected
Expand Down
5 changes: 2 additions & 3 deletions cli/command/formatter/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ import (

"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/stringid"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/golden"
)

func TestContainerPsContext(t *testing.T) {
containerID := stringid.GenerateRandomID()
containerID := test.RandomID()
unix := time.Now().Add(-65 * time.Second).Unix()

var ctx ContainerContext
Expand All @@ -34,7 +33,7 @@ func TestContainerPsContext(t *testing.T) {
{
container: container.Summary{ID: containerID},
trunc: true,
expValue: stringid.TruncateID(containerID),
expValue: TruncateID(containerID),
call: ctx.ID,
},
{
Expand Down
2 changes: 1 addition & 1 deletion cli/command/formatter/disk_usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/volume"
units "github.com/docker/go-units"
"github.com/docker/go-units"
)

const (
Expand Down
19 changes: 19 additions & 0 deletions cli/command/formatter/displayutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ func charWidth(r rune) int {
}
}

const shortLen = 12

// TruncateID returns a shorthand version of a string identifier for presentation,
// after trimming digest algorithm prefix (if any).
//
// This function is a copy of [stringid.TruncateID] for presentation / formatting
// purposes.
//
// [stringid.TruncateID]: https://github.com/moby/moby/blob/v28.3.2/pkg/stringid/stringid.go#L19
func TruncateID(id string) string {
if i := strings.IndexRune(id, ':'); i >= 0 {
id = id[i+1:]
}
if len(id) > shortLen {
id = id[:shortLen]
}
return id
}

// Ellipsis truncates a string to fit within maxDisplayWidth, and appends ellipsis (…).
// For maxDisplayWidth of 1 and lower, no ellipsis is appended.
// For maxDisplayWidth of 1, first char of string will return even if its width > 1.
Expand Down
43 changes: 43 additions & 0 deletions cli/command/formatter/displayutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,49 @@ import (
is "gotest.tools/v3/assert/cmp"
)

func TestTruncateID(t *testing.T) {
tests := []struct {
doc, id, expected string
}{
{
doc: "empty ID",
id: "",
expected: "",
},
{
// IDs are expected to be 12 (short) or 64 characters, and not be numeric only,
// but TruncateID should handle these gracefully.
doc: "invalid ID",
id: "1234",
expected: "1234",
},
{
doc: "full ID",
id: "90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2",
expected: "90435eec5c4e",
},
{
doc: "digest",
id: "sha256:90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2",
expected: "90435eec5c4e",
},
{
doc: "very long ID",
id: "90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a290435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2",
expected: "90435eec5c4e",
},
}

for _, tc := range tests {
t.Run(tc.doc, func(t *testing.T) {
actual := TruncateID(tc.id)
if actual != tc.expected {
t.Errorf("expected: %q, got: %q", tc.expected, actual)
}
})
}
}

func TestEllipsis(t *testing.T) {
testcases := []struct {
source string
Expand Down
5 changes: 2 additions & 3 deletions cli/command/formatter/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import (

"github.com/distribution/reference"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/pkg/stringid"
units "github.com/docker/go-units"
"github.com/docker/go-units"
)

const (
Expand Down Expand Up @@ -216,7 +215,7 @@ func (c *imageContext) MarshalJSON() ([]byte, error) {

func (c *imageContext) ID() string {
if c.trunc {
return stringid.TruncateID(c.i.ID)
return TruncateID(c.i.ID)
}
return c.i.ID
}
Expand Down
Loading