docker / docker/cli

docker run -i can hang and leak a container if started with stdin closed

Open
#2,542 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area/ux
Dominant language
Go
Stars
6.1k
Forks
2.2k
Avg merge
1d 15h
Merged PRs (30d)
43

Description

Follow up from https://github.com/moby/moby/issues/41015

How to reproduce
go run the following cocde

package main

import (
	"fmt"
	"os"
	"time"
)

func main() {
	name := "/usr/bin/docker"
	args := []string{"run", "--rm", "-i", "busybox", "sleep", "1"}

	//devNull, _ := os.Open(os.DevNull)

	for {
		fmt.Printf("Executing: \"%s\" %v\n", name, args)
		proc, err := os.StartProcess(name, append([]string{name}, args...), &os.ProcAttr{
			Files: []*os.File{nil, nil, nil},
		})
		if err != nil {
			panic(err)
		}
		fmt.Println(time.Now(), "Wait on exit")
		proc.Wait()
		fmt.Println("Done")
	}
}

Here we docker run in a loop with -i and no stdin, stdout, or stderr

It will work for a while, and eventually hang. When it is hanging, you can see the docker run process has created a container but the CLI is hanging on
https://github.com/docker/cli/blob/590f3271ef098f1e11dfbd84d8596b7bf1561c36/cli/command/container/run.go#L165

So the container is never started

$ ps -ef | grep "docker run"
bbuzbee   7384  7234  0 10:04 pts/0    00:00:00 /usr/bin/docker run --rm -i busybox sleep 1
 docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
ddd9cc922c41        busybox             "sleep 1"           4 minutes ago       Created                                 tender_hamilton

Analysis
If you remove -i from docker run, the issue goes away.

If you pass the devNull FD I have commented out to stdin, such as

			Files: []*os.File{devNull, nil, nil},

then the issue goes away.

The CLI is hung waiting on headers to be returned to the call to the docker daemon's /wait endpoint, and I confirmed the daemon has flushed headers so I do not know what it is waiting on. Maybe it is because flush doesn't call fflush but I am not sure how that could be related to attach.

Thoughts
I don't know the design goals, but if -i without stdin is not supported I think it should exit with an error rather than hang. Also seems to be a race since it works sometimes.

Thanks

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the loop from the issue with docker run --rm -i busybox sleep 1 and stdin, stdout, and stderr closed. Start at cli/command/container/run.go around line 165 and trace the CLI's wait and attach behavior alongside the daemon's /wait endpoint. Done means the command no longer hangs or leaves a Created container, with the supported behavior for closed stdin established.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, go
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.