diff --git a/mount/init.go b/mount/init.go index 0de9a83c0..91a27294a 100644 --- a/mount/init.go +++ b/mount/init.go @@ -82,7 +82,7 @@ func InitializeMountNamespace(rootfs, console string, sysReadonly bool, hostRoot if mountConfig.NoPivotRoot { err = MsMoveRoot(rootfs) } else { - err = PivotRoot(rootfs) + err = PivotRoot(rootfs, mountConfig.PivotDir) } if err != nil { diff --git a/mount/mount_config.go b/mount/mount_config.go index eef9b8ce4..f19465e60 100644 --- a/mount/mount_config.go +++ b/mount/mount_config.go @@ -13,6 +13,11 @@ type MountConfig struct { // This is a common option when the container is running in ramdisk NoPivotRoot bool `json:"no_pivot_root,omitempty"` + // PivotDir allows a custom directory inside the container's root filesystem to be used as pivot, when NoPivotRoot is not set. + // When a custom PivotDir not set, a temporary dir inside the root filesystem will be used. The pivot dir needs to be writeable. + // This is required when using read only root filesystems. In these cases, a read/writeable path can be (bind) mounted somewhere inside the root filesystem to act as pivot. + PivotDir string `json:"pivot_dir,omitempty"` + // ReadonlyFs will remount the container's rootfs as readonly where only externally mounted // bind mounts are writtable ReadonlyFs bool `json:"readonly_fs,omitempty"` diff --git a/mount/pivotroot.go b/mount/pivotroot.go index a88ed4a84..acc3be24c 100644 --- a/mount/pivotroot.go +++ b/mount/pivotroot.go @@ -10,8 +10,15 @@ import ( "syscall" ) -func PivotRoot(rootfs string) error { - pivotDir, err := ioutil.TempDir(rootfs, ".pivot_root") +func PivotRoot(rootfs, pivotBaseDir string) error { + if pivotBaseDir == "" { + pivotBaseDir = "/" + } + tmpDir := filepath.Join(rootfs, pivotBaseDir) + if err := os.MkdirAll(tmpDir, 0755); err != nil { + return fmt.Errorf("can't create tmp dir %s, error %v", tmpDir, err) + } + pivotDir, err := ioutil.TempDir(tmpDir, ".pivot_root") if err != nil { return fmt.Errorf("can't create pivot_root dir %s, error %v", pivotDir, err) } @@ -25,7 +32,7 @@ func PivotRoot(rootfs string) error { } // path to pivot dir now changed, update - pivotDir = filepath.Join("/", filepath.Base(pivotDir)) + pivotDir = filepath.Join(pivotBaseDir, filepath.Base(pivotDir)) if err := syscall.Unmount(pivotDir, syscall.MNT_DETACH); err != nil { return fmt.Errorf("unmount pivot_root dir %s", err) }