New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't create source directory while the daemon is being shutdown, fix #30348 #33330
Conversation
|
@coolljt0725 looks like build is failing; |
83328f5
to
806c5e8
Compare
|
@thaJeztah updated |
|
ping @cpuguy83 @mlaventure PTAL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few nits and a requested change to checkFun prototype.
Otherwise, LGTM. Thanks for finding this!
daemon/volumes_unix.go
Outdated
| @@ -42,8 +43,21 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er | |||
| if err := daemon.lazyInitializeVolume(c.ID, m); err != nil { | |||
| return nil, err | |||
| } | |||
| // if the daemon is being shutdown, we could not let the container | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
If the daemon is being shutdown, we should not let a container start if it is trying to mount the socket the daemon is listening on. During daemon shutdown, the socket (
/var/run/docker.sockby default) doesn't exist anymore causing the call tom.Setupto create at directory instead. This in turn will prevent the daemon to restart.
daemon/volumes_unix.go
Outdated
| // the socket (`/var/run/docker.sock` by default) does not exist and | ||
| // the m.Setup will assume it's a directory and create it, this will | ||
| // cause the daemon can't start next time. | ||
| checkfunc := func() error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd prefer the callback to be of the form func(m *Mountpoint) error
volume/volume.go
Outdated
| @@ -146,7 +146,9 @@ func (m *MountPoint) Cleanup() error { | |||
|
|
|||
| // Setup sets up a mount point by either mounting the volume if it is | |||
| // configured, or creating the source directory if supplied. | |||
| func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (path string, err error) { | |||
| // The checkFun is to do some checking before creating the | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
The, optional, checkFun parameter allows doing additional checking before creating the source directory on the host.
volume/volume.go
Outdated
| @@ -181,6 +183,14 @@ func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (path string | |||
|
|
|||
| // system.MkdirAll() produces an error if m.Source exists and is a file (not a directory), | |||
| if m.Type == mounttypes.TypeBind { | |||
| // Before creating source directory on the host do the checking if it's not nil | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
Before creating the source directory on the host, invoke
checkFunif it's not nil. One of the use case is to forbid creating the daemon socket as a directory if the daemon is in the process of shutting down.
806c5e8
to
7318eba
Compare
|
@mlaventure update |
…oby#30348 If a container mount the socket the daemon is listening on into container while the daemon is being shutdown, the socket will not exist on the host, then daemon will assume it's a directory and create it on the host, this will cause the daemon can't start next time. fix issue moby#30348 To reproduce this issue, you can add following code ``` --- a/daemon/oci_linux.go +++ b/daemon/oci_linux.go @@ -8,6 +8,7 @@ import ( "sort" "strconv" "strings" + "time" "github.com/Sirupsen/logrus" "github.com/docker/docker/container" @@ -666,7 +667,8 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e if err := daemon.setupIpcDirs(c); err != nil { return nil, err } - + fmt.Printf("===please stop the daemon===\n") + time.Sleep(time.Second * 2) ms, err := daemon.setupMounts(c) if err != nil { return nil, err ``` step1 run a container which has `--restart always` and `-v /var/run/docker.sock:/sock` ``` $ docker run -ti --restart always -v /var/run/docker.sock:/sock busybox / # ``` step2 exit the the container ``` / # exit ``` and kill the daemon when you see ``` ===please stop the daemon=== ``` in the daemon log The daemon can't restart again and fail with `can't create unix socket /var/run/docker.sock: is a directory`. Signed-off-by: Lei Jitang <leijitang@huawei.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thanks!
| // StoreHosts stores the addresses the daemon is listening on | ||
| func (daemon *Daemon) StoreHosts(hosts []string) { | ||
| if daemon.hosts == nil { | ||
| daemon.hosts = make(map[string]bool) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we initialize daemon.hosts in NewDaemon()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have considered that, but it will have some duplicate code to dealing with the hosts config (https://github.com/moby/moby/blob/master/cmd/dockerd/daemon.go#L157).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
If a container mount the socket the daemon is listening on into
container while the daemon is being shutdown, the socket will
not exist on the host, then daemon will assume it's a directory
and create it on the host, this will cause the daemon can't start
next time.
fix issue #30348
To reproduce this issue, you can add following code
step1 run a container which has
--restart alwaysand-v /var/run/docker.sock:/sockstep2 exit the the container
and kill the daemon when you see
in the daemon log
The daemon can't restart again and fail with
can't create unix socket /var/run/docker.sock: is a directory.Signed-off-by: Lei Jitang leijitang@huawei.com
ping @cpuguy83 @thaJeztah
- What I did
- How I did it
- How to verify it
- Description for the changelog
- A picture of a cute animal (not mandatory but encouraged)