diff --git a/daemon/graphdriver/aufs/aufs.go b/daemon/graphdriver/aufs/aufs.go index 5c8662488b..fd854d0f55 100644 --- a/daemon/graphdriver/aufs/aufs.go +++ b/daemon/graphdriver/aufs/aufs.go @@ -23,6 +23,7 @@ package aufs import ( "bufio" "fmt" + "io/ioutil" "os" "os/exec" "path" @@ -47,6 +48,9 @@ var ( graphdriver.FsMagicAufs, } backingFs = "" + + enableDirpermLock sync.Once + enableDirperm bool ) func init() { @@ -152,6 +156,7 @@ func (a *Driver) Status() [][2]string { {"Root Dir", a.rootPath()}, {"Backing Filesystem", backingFs}, {"Dirs", fmt.Sprintf("%d", len(ids))}, + {"Dirperm1 Supported", fmt.Sprintf("%v", useDirperm())}, } } @@ -422,7 +427,11 @@ func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err erro // Mount options are clipped to page size(4096 bytes). If there are more // layers then these are remounted individually using append. - b := make([]byte, syscall.Getpagesize()-len(mountLabel)-54) // room for xino & mountLabel + offset := 54 + if useDirperm() { + offset += len("dirperm1") + } + b := make([]byte, syscall.Getpagesize()-len(mountLabel)-offset) // room for xino & mountLabel bp := copy(b, fmt.Sprintf("br:%s=rw", rw)) firstMount := true @@ -446,7 +455,11 @@ func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err erro } if firstMount { - data := label.FormatMountLabel(fmt.Sprintf("%s,dio,xino=/dev/shm/aufs.xino", string(b[:bp])), mountLabel) + opts := "dio,xino=/dev/shm/aufs.xino" + if useDirperm() { + opts += ",dirperm1" + } + data := label.FormatMountLabel(fmt.Sprintf("%s,%s", string(b[:bp]), opts), mountLabel) if err = mount("none", target, "aufs", 0, data); err != nil { return } @@ -460,3 +473,33 @@ func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err erro return } + +// useDirperm checks dirperm1 mount option can be used with the current +// version of aufs. +func useDirperm() bool { + enableDirpermLock.Do(func() { + base, err := ioutil.TempDir("", "docker-aufs-base") + if err != nil { + log.Errorf("error checking dirperm1: %v", err) + return + } + defer os.RemoveAll(base) + + union, err := ioutil.TempDir("", "docker-aufs-union") + if err != nil { + log.Errorf("error checking dirperm1: %v", err) + return + } + defer os.RemoveAll(union) + + opts := fmt.Sprintf("br:%s,dirperm1,xino=/dev/shm/aufs.xino", base) + if err := mount("none", union, "aufs", 0, opts); err != nil { + return + } + enableDirperm = true + if err := Unmount(union); err != nil { + log.Errorf("error checking dirperm1: failed to unmount %v", err) + } + }) + return enableDirperm +} diff --git a/docs/sources/reference/builder.md b/docs/sources/reference/builder.md index 46d0e21e88..adf42ae764 100644 --- a/docs/sources/reference/builder.md +++ b/docs/sources/reference/builder.md @@ -280,8 +280,14 @@ The cache for `RUN` instructions can be invalidated by `ADD` instructions. See - [Issue 783](https://github.com/docker/docker/issues/783) is about file permissions problems that can occur when using the AUFS file system. You - might notice it during an attempt to `rm` a file, for example. The issue - describes a workaround. + might notice it during an attempt to `rm` a file, for example. + + For systems that have recent aufs version (i.e., `dirperm1` mount option can + be set), docker will attempt to fix the issue automatically by mounting + the layers with `dirperm1` option. More details on `dirperm1` option can be + found at [`aufs` man page](http://aufs.sourceforge.net/aufs3/man.html) + + If your system doesnt have support for `dirperm1`, the issue describes a workaround. ## CMD diff --git a/docs/sources/release-notes.md b/docs/sources/release-notes.md index 37ae6761aa..fe79d881dc 100644 --- a/docs/sources/release-notes.md +++ b/docs/sources/release-notes.md @@ -57,7 +57,14 @@ impact on users. This list will be updated as issues are resolved. * **Unexpected File Permissions in Containers** An idiosyncrasy in AUFS prevents permissions from propagating predictably between upper and lower layers. This can cause issues with accessing private -keys, database instances, etc. For complete information and workarounds see +keys, database instances, etc. + +For systems that have recent aufs version (i.e., `dirperm1` mount option can +be set), docker will attempt to fix the issue automatically by mounting +the layers with `dirperm1` option. More details on `dirperm1` option can be +found at [`aufs` man page](http://aufs.sourceforge.net/aufs3/man.html) + +For complete information and workarounds see [Github Issue 783](https://github.com/docker/docker/issues/783). * **Docker Hub incompatible with Safari 8**