Support read-only root filesystems
The only place I could find where libcontainer tries to write to the container's root FS is when setting up the pivot dir, to be used on pivot_root(2). This makes the pivot base dir configurable, so a read-only FS can be used as root FS of containers. Users can then specify a writeable subpath to be used as pivot inside the container. Signed-off-by: Fabio Kung <fabio@heroku.com> (github: fabiokung)
This commit is contained in:
parent
1d3b2589d7
commit
2a452c17aa
|
@ -79,7 +79,7 @@ func InitializeMountNamespace(rootfs, console string, sysReadonly bool, mountCon
|
||||||
if mountConfig.NoPivotRoot {
|
if mountConfig.NoPivotRoot {
|
||||||
err = MsMoveRoot(rootfs)
|
err = MsMoveRoot(rootfs)
|
||||||
} else {
|
} else {
|
||||||
err = PivotRoot(rootfs)
|
err = PivotRoot(rootfs, mountConfig.PivotDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -13,6 +13,11 @@ type MountConfig struct {
|
||||||
// This is a common option when the container is running in ramdisk
|
// This is a common option when the container is running in ramdisk
|
||||||
NoPivotRoot bool `json:"no_pivot_root,omitempty"`
|
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
|
// ReadonlyFs will remount the container's rootfs as readonly where only externally mounted
|
||||||
// bind mounts are writtable
|
// bind mounts are writtable
|
||||||
ReadonlyFs bool `json:"readonly_fs,omitempty"`
|
ReadonlyFs bool `json:"readonly_fs,omitempty"`
|
||||||
|
|
|
@ -10,8 +10,15 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func PivotRoot(rootfs string) error {
|
func PivotRoot(rootfs, pivotBaseDir string) error {
|
||||||
pivotDir, err := ioutil.TempDir(rootfs, ".pivot_root")
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("can't create pivot_root dir %s, error %v", pivotDir, err)
|
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
|
// 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 {
|
if err := syscall.Unmount(pivotDir, syscall.MNT_DETACH); err != nil {
|
||||||
return fmt.Errorf("unmount pivot_root dir %s", err)
|
return fmt.Errorf("unmount pivot_root dir %s", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue