From 2cfee9ff867d9d14ee5f8aa61d37f3e3bdf82b10 Mon Sep 17 00:00:00 2001 From: Dean Chen <862469039@qq.com> Date: Wed, 26 Aug 2026 02:49:23 +0500 Subject: [PATCH] container: allow an empty --cidfile path from mktemp newCIDFile currently errors if the path already exists, even when the file is empty. mktemp creates that empty file first, so `docker run --cidfile=$(mktemp)` always fails. Keep refusing a path that already holds a container ID. Open/create otherwise so an empty file can be reused. Fixes #5954 Signed-off-by: Dean Chen <862469039@qq.com> --- cli/command/container/create.go | 15 +++++++++++---- cli/command/container/create_test.go | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/cli/command/container/create.go b/cli/command/container/create.go index 122d15e2e149..cb67b964b178 100644 --- a/cli/command/container/create.go +++ b/cli/command/container/create.go @@ -198,14 +198,21 @@ func newCIDFile(cidPath string) (*cidFile, error) { if cidPath == "" { return &cidFile{}, nil } - if _, err := os.Stat(cidPath); err == nil { - return nil, errors.New("container ID file found, make sure the other container isn't running or delete " + cidPath) + // mktemp (and similar) create an empty file first. Only refuse the path + // when it already holds a container ID from another run. + f, err := os.OpenFile(cidPath, os.O_RDWR|os.O_CREATE, 0o644) + if err != nil { + return nil, fmt.Errorf("failed to create the container ID file: %w", err) } - - f, err := os.Create(cidPath) + st, err := f.Stat() if err != nil { + _ = f.Close() return nil, fmt.Errorf("failed to create the container ID file: %w", err) } + if st.Size() > 0 { + _ = f.Close() + return nil, errors.New("container ID file found, make sure the other container isn't running or delete " + cidPath) + } return &cidFile{path: cidPath, file: f}, nil } diff --git a/cli/command/container/create_test.go b/cli/command/container/create_test.go index 1c6ec9264975..67c66f00c2ed 100644 --- a/cli/command/container/create_test.go +++ b/cli/command/container/create_test.go @@ -37,11 +37,27 @@ func TestCIDFileNoOPWithNoFilename(t *testing.T) { func TestNewCIDFileWhenFileAlreadyExists(t *testing.T) { tempfile := fs.NewFile(t, "test-cid-file") defer tempfile.Remove() + assert.NilError(t, os.WriteFile(tempfile.Path(), []byte("already-running"), 0o644)) _, err := newCIDFile(tempfile.Path()) assert.ErrorContains(t, err, "container ID file found") } +func TestNewCIDFileWhenEmptyFileExists(t *testing.T) { + tempfile := fs.NewFile(t, "test-cid-file") + defer tempfile.Remove() + + file, err := newCIDFile(tempfile.Path()) + assert.NilError(t, err) + + assert.NilError(t, file.Write("id")) + assert.NilError(t, file.Close()) + + actual, err := os.ReadFile(tempfile.Path()) + assert.NilError(t, err) + assert.Check(t, is.Equal("id", string(actual))) +} + func TestCIDFileCloseWithNoWrite(t *testing.T) { // Closing should remove the file if it was not written to. t.Run("closing should remove file", func(t *testing.T) {