@@ -446,6 +446,10 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
446446 return err
447447 }
448448
449+ if err := ioutil .WriteFile (path .Join (d .dir (parent ), "committed" ), []byte {}, 0600 ); err != nil {
450+ return err
451+ }
452+
449453 lower , err := d .getLower (parent )
450454 if err != nil {
451455 return err
@@ -592,7 +596,20 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
592596 for i , s := range splitLowers {
593597 absLowers [i ] = path .Join (d .home , s )
594598 }
595- opts := indexOff + "lowerdir=" + strings .Join (absLowers , ":" ) + ",upperdir=" + diffDir + ",workdir=" + workDir
599+ var readonly bool
600+ if _ , err := os .Stat (path .Join (dir , "committed" )); err == nil {
601+ readonly = true
602+ } else if ! os .IsNotExist (err ) {
603+ return nil , err
604+ }
605+
606+ var opts string
607+ if readonly {
608+ opts = indexOff + "lowerdir=" + diffDir + ":" + strings .Join (absLowers , ":" )
609+ } else {
610+ opts = indexOff + "lowerdir=" + strings .Join (absLowers , ":" ) + ",upperdir=" + diffDir + ",workdir=" + workDir
611+ }
612+
596613 mountData := label .FormatMountLabel (opts , mountLabel )
597614 mount := unix .Mount
598615 mountTarget := mergedDir
@@ -612,7 +629,11 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
612629 // fit within a page and relative links make the mount data much
613630 // smaller at the expense of requiring a fork exec to chroot.
614631 if len (mountData ) > pageSize {
615- opts = indexOff + "lowerdir=" + string (lowers ) + ",upperdir=" + path .Join (id , diffDirName ) + ",workdir=" + path .Join (id , workDirName )
632+ if readonly {
633+ opts = indexOff + "lowerdir=" + path .Join (id , diffDirName ) + ":" + string (lowers )
634+ } else {
635+ opts = indexOff + "lowerdir=" + string (lowers ) + ",upperdir=" + path .Join (id , diffDirName ) + ",workdir=" + path .Join (id , workDirName )
636+ }
616637 mountData = label .FormatMountLabel (opts , mountLabel )
617638 if len (mountData ) > pageSize {
618639 return nil , fmt .Errorf ("cannot mount layer, mount label too large %d" , len (mountData ))
@@ -628,10 +649,12 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
628649 return nil , fmt .Errorf ("error creating overlay mount to %s: %v" , mergedDir , err )
629650 }
630651
631- // chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
632- // user namespace requires this to move a directory from lower to upper.
633- if err := os .Chown (path .Join (workDir , workDirName ), rootUID , rootGID ); err != nil {
634- return nil , err
652+ if ! readonly {
653+ // chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
654+ // user namespace requires this to move a directory from lower to upper.
655+ if err := os .Chown (path .Join (workDir , workDirName ), rootUID , rootGID ); err != nil {
656+ return nil , err
657+ }
635658 }
636659
637660 return containerfs .NewLocalContainerFS (mergedDir ), nil
0 commit comments