mirror of https://github.com/docker/docs.git
Improve interface by moving to subpkg
Enable builds on OSX
This commit is contained in:
parent
a6fdc5d208
commit
7bc96aec7b
57
container.go
57
container.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker/archive"
|
"github.com/dotcloud/docker/archive"
|
||||||
"github.com/dotcloud/docker/graphdriver"
|
"github.com/dotcloud/docker/graphdriver"
|
||||||
|
"github.com/dotcloud/docker/mount"
|
||||||
"github.com/dotcloud/docker/term"
|
"github.com/dotcloud/docker/term"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"github.com/kr/pty"
|
"github.com/kr/pty"
|
||||||
|
@ -684,13 +685,41 @@ func (container *Container) Start() (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mounts, err := runtime.getMounts(container)
|
root := container.RootfsPath()
|
||||||
|
envPath, err := container.EnvConfigPath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range mounts {
|
// Mount docker specific files into the containers root fs
|
||||||
if err := m.Mount(container.RootfsPath()); err != nil {
|
if err := mount.Mount(runtime.sysInitPath, path.Join(root, "/.dockerinit"), "none", "bind,ro"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := mount.Mount(envPath, path.Join(root, "/.dockerenv"), "none", "bind,ro"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := mount.Mount(container.ResolvConfPath, path.Join(root, "/etc/resolv.conf"), "none", "bind,ro"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if container.HostnamePath != "" && container.HostsPath != "" {
|
||||||
|
if err := mount.Mount(container.HostnamePath, path.Join(root, "/etc/hostname"), "none", "bind,ro"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := mount.Mount(container.HostsPath, path.Join(root, "/etc/hosts"), "none", "bind,ro"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount user specified volumes
|
||||||
|
|
||||||
|
for r, v := range container.Volumes {
|
||||||
|
mountAs := "ro"
|
||||||
|
if container.VolumesRW[v] {
|
||||||
|
mountAs = "rw"
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mount.Mount(v, path.Join(root, r), "none", fmt.Sprintf("bind,%s", mountAs)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1372,12 +1401,26 @@ func (container *Container) GetImage() (*Image, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) Unmount() error {
|
func (container *Container) Unmount() error {
|
||||||
mounts, err := container.runtime.getMounts(container)
|
var (
|
||||||
if err != nil {
|
err error
|
||||||
return err
|
root = container.RootfsPath()
|
||||||
|
mounts = []string{
|
||||||
|
path.Join(root, "/.dockerinit"),
|
||||||
|
path.Join(root, "/.dockerenv"),
|
||||||
|
path.Join(root, "/etc/resolv.conf"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if container.HostnamePath != "" && container.HostsPath != "" {
|
||||||
|
mounts = append(mounts, path.Join(root, "/etc/hostname"), path.Join(root, "/etc/hosts"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for r := range container.Volumes {
|
||||||
|
mounts = append(mounts, path.Join(root, r))
|
||||||
|
}
|
||||||
|
|
||||||
for _, m := range mounts {
|
for _, m := range mounts {
|
||||||
if lastError := m.Unmount(container.RootfsPath()); lastError != nil {
|
if lastError := mount.Unmount(m); lastError != nil {
|
||||||
err = lastError
|
err = lastError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker/archive"
|
"github.com/dotcloud/docker/archive"
|
||||||
"github.com/dotcloud/docker/graphdriver"
|
"github.com/dotcloud/docker/graphdriver"
|
||||||
|
mountpk "github.com/dotcloud/docker/mount"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -295,7 +296,7 @@ func (a *Driver) unmount(id string) error {
|
||||||
|
|
||||||
func (a *Driver) mounted(id string) (bool, error) {
|
func (a *Driver) mounted(id string) (bool, error) {
|
||||||
target := path.Join(a.rootPath(), "mnt", id)
|
target := path.Join(a.rootPath(), "mnt", id)
|
||||||
return graphdriver.Mounted(target)
|
return mountpk.Mounted(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// During cleanup aufs needs to unmount all mountpoints
|
// During cleanup aufs needs to unmount all mountpoints
|
||||||
|
|
|
@ -1,19 +1,13 @@
|
||||||
package graphdriver
|
package graphdriver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker/archive"
|
"github.com/dotcloud/docker/archive"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const mountinfoFormat = "%d %d %d:%d %s %s %s - %s %s %s"
|
|
||||||
|
|
||||||
type InitFunc func(root string) (Driver, error)
|
type InitFunc func(root string) (Driver, error)
|
||||||
|
|
||||||
type Driver interface {
|
type Driver interface {
|
||||||
|
@ -37,13 +31,6 @@ type Differ interface {
|
||||||
DiffSize(id string) (bytes int64, err error)
|
DiffSize(id string) (bytes int64, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mount struct {
|
|
||||||
Device string
|
|
||||||
Target string
|
|
||||||
Type string
|
|
||||||
Options string
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DefaultDriver string
|
DefaultDriver string
|
||||||
// All registred drivers
|
// All registred drivers
|
||||||
|
@ -101,137 +88,3 @@ func New(root string) (driver Driver, err error) {
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mount) Mount(root string) error {
|
|
||||||
target := path.Join(root, m.Target)
|
|
||||||
if mounted, err := Mounted(target); err != nil || mounted {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
flag, data := parseOptions(m.Options)
|
|
||||||
if err := syscall.Mount(m.Device, target, m.Type, uintptr(flag), data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseOptions(options string) (int, string) {
|
|
||||||
var (
|
|
||||||
flag int
|
|
||||||
data []string
|
|
||||||
)
|
|
||||||
|
|
||||||
flags := map[string]struct {
|
|
||||||
clear bool
|
|
||||||
flag int
|
|
||||||
}{
|
|
||||||
"defaults": {false, 0},
|
|
||||||
"ro": {false, syscall.MS_RDONLY},
|
|
||||||
"rw": {true, syscall.MS_RDONLY},
|
|
||||||
"suid": {true, syscall.MS_NOSUID},
|
|
||||||
"nosuid": {false, syscall.MS_NOSUID},
|
|
||||||
"dev": {true, syscall.MS_NODEV},
|
|
||||||
"nodev": {false, syscall.MS_NODEV},
|
|
||||||
"exec": {true, syscall.MS_NOEXEC},
|
|
||||||
"noexec": {false, syscall.MS_NOEXEC},
|
|
||||||
"sync": {false, syscall.MS_SYNCHRONOUS},
|
|
||||||
"async": {true, syscall.MS_SYNCHRONOUS},
|
|
||||||
"dirsync": {false, syscall.MS_DIRSYNC},
|
|
||||||
"remount": {false, syscall.MS_REMOUNT},
|
|
||||||
"mand": {false, syscall.MS_MANDLOCK},
|
|
||||||
"nomand": {true, syscall.MS_MANDLOCK},
|
|
||||||
"atime": {true, syscall.MS_NOATIME},
|
|
||||||
"noatime": {false, syscall.MS_NOATIME},
|
|
||||||
"diratime": {true, syscall.MS_NODIRATIME},
|
|
||||||
"nodiratime": {false, syscall.MS_NODIRATIME},
|
|
||||||
"bind": {false, syscall.MS_BIND},
|
|
||||||
"rbind": {false, syscall.MS_BIND | syscall.MS_REC},
|
|
||||||
"relatime": {false, syscall.MS_RELATIME},
|
|
||||||
"norelatime": {true, syscall.MS_RELATIME},
|
|
||||||
"strictatime": {false, syscall.MS_STRICTATIME},
|
|
||||||
"nostrictatime": {true, syscall.MS_STRICTATIME},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, o := range strings.Split(options, ",") {
|
|
||||||
// If the option does not exist in the flags table then it is a
|
|
||||||
// data value for a specific fs type
|
|
||||||
if f, exists := flags[o]; exists {
|
|
||||||
if f.clear {
|
|
||||||
flag &= ^f.flag
|
|
||||||
} else {
|
|
||||||
flag |= f.flag
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
data = append(data, o)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return flag, strings.Join(data, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mount) Unmount(root string) (err error) {
|
|
||||||
target := path.Join(root, m.Target)
|
|
||||||
if mounted, err := Mounted(target); err != nil || !mounted {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple retry logic for unmount
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
if err = syscall.Unmount(target, 0); err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
utils.Debugf("[Unmount] %s", err)
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func Mounted(mountpoint string) (bool, error) {
|
|
||||||
entries, err := parseMountTable()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search the table for the mountpoint
|
|
||||||
for _, e := range entries {
|
|
||||||
if e.mountpoint == mountpoint {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Represents one line from /proc/self/mountinfo
|
|
||||||
type procEntry struct {
|
|
||||||
id, parent, major, minor int
|
|
||||||
source, mountpoint, fstype, device string
|
|
||||||
vfsopts, opts string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse /proc/self/mountinfo because comparing Dev and ino does not work from bind mounts
|
|
||||||
//
|
|
||||||
// 180 20 0:2851 / /var/lib/docker/aufs/mnt/a22632d4ed3cb2438246064408f9f07734cbd331f50c81f1ca3dcbd78541ce83 rw,relatime - aufs none rw,si=e9663ac1adbdb4f8
|
|
||||||
func parseMountTable() ([]*procEntry, error) {
|
|
||||||
f, err := os.Open("/proc/self/mountinfo")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
s := bufio.NewScanner(f)
|
|
||||||
out := []*procEntry{}
|
|
||||||
for s.Scan() {
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
p := &procEntry{}
|
|
||||||
if _, err := fmt.Sscanf(s.Text(), mountinfoFormat,
|
|
||||||
&p.id, &p.parent, &p.major, &p.minor,
|
|
||||||
&p.source, &p.mountpoint, &p.vfsopts, &p.fstype,
|
|
||||||
&p.device, &p.opts); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
out = append(out, p)
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
|
|
@ -0,0 +1,5 @@
|
||||||
|
package mount
|
||||||
|
|
||||||
|
func parseOptions(options string) (int, string) {
|
||||||
|
panic("Not implemented")
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package mount
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Parse fstab type mount options into mount() flags
|
||||||
|
// and device specific data
|
||||||
|
func parseOptions(options string) (int, string) {
|
||||||
|
var (
|
||||||
|
flag int
|
||||||
|
data []string
|
||||||
|
)
|
||||||
|
|
||||||
|
flags := map[string]struct {
|
||||||
|
clear bool
|
||||||
|
flag int
|
||||||
|
}{
|
||||||
|
"defaults": {false, 0},
|
||||||
|
"ro": {false, syscall.MS_RDONLY},
|
||||||
|
"rw": {true, syscall.MS_RDONLY},
|
||||||
|
"suid": {true, syscall.MS_NOSUID},
|
||||||
|
"nosuid": {false, syscall.MS_NOSUID},
|
||||||
|
"dev": {true, syscall.MS_NODEV},
|
||||||
|
"nodev": {false, syscall.MS_NODEV},
|
||||||
|
"exec": {true, syscall.MS_NOEXEC},
|
||||||
|
"noexec": {false, syscall.MS_NOEXEC},
|
||||||
|
"sync": {false, syscall.MS_SYNCHRONOUS},
|
||||||
|
"async": {true, syscall.MS_SYNCHRONOUS},
|
||||||
|
"dirsync": {false, syscall.MS_DIRSYNC},
|
||||||
|
"remount": {false, syscall.MS_REMOUNT},
|
||||||
|
"mand": {false, syscall.MS_MANDLOCK},
|
||||||
|
"nomand": {true, syscall.MS_MANDLOCK},
|
||||||
|
"atime": {true, syscall.MS_NOATIME},
|
||||||
|
"noatime": {false, syscall.MS_NOATIME},
|
||||||
|
"diratime": {true, syscall.MS_NODIRATIME},
|
||||||
|
"nodiratime": {false, syscall.MS_NODIRATIME},
|
||||||
|
"bind": {false, syscall.MS_BIND},
|
||||||
|
"rbind": {false, syscall.MS_BIND | syscall.MS_REC},
|
||||||
|
"relatime": {false, syscall.MS_RELATIME},
|
||||||
|
"norelatime": {true, syscall.MS_RELATIME},
|
||||||
|
"strictatime": {false, syscall.MS_STRICTATIME},
|
||||||
|
"nostrictatime": {true, syscall.MS_STRICTATIME},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range strings.Split(options, ",") {
|
||||||
|
// If the option does not exist in the flags table then it is a
|
||||||
|
// data value for a specific fs type
|
||||||
|
if f, exists := flags[o]; exists {
|
||||||
|
if f.clear {
|
||||||
|
flag &= ^f.flag
|
||||||
|
} else {
|
||||||
|
flag |= f.flag
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = append(data, o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flag, strings.Join(data, ",")
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package mount
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Looks at /proc/self/mountinfo to determine of the specified
|
||||||
|
// mountpoint has been mounted
|
||||||
|
func Mounted(mountpoint string) (bool, error) {
|
||||||
|
entries, err := parseMountTable()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search the table for the mountpoint
|
||||||
|
for _, e := range entries {
|
||||||
|
if e.mountpoint == mountpoint {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount the specified options at the target path
|
||||||
|
// Options must be specified as fstab style
|
||||||
|
func Mount(device, target, mType, options string) error {
|
||||||
|
if mounted, err := Mounted(target); err != nil || mounted {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
flag, data := parseOptions(options)
|
||||||
|
if err := mount(device, target, mType, uintptr(flag), data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmount the target only if it is mounted
|
||||||
|
func Unmount(target string) (err error) {
|
||||||
|
if mounted, err := Mounted(target); err != nil || !mounted {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple retry logic for unmount
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
if err = unmount(target, 0); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package graphdriver
|
package mount
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
@ -24,7 +24,7 @@ func TestMountOptionsParsing(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMounted(t *testing.T) {
|
func TestMounted(t *testing.T) {
|
||||||
tmp := path.Join(os.TempDir(), "graphdriver-tests")
|
tmp := path.Join(os.TempDir(), "mount-tests")
|
||||||
if err := os.MkdirAll(tmp, 0777); err != nil {
|
if err := os.MkdirAll(tmp, 0777); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -48,18 +48,11 @@ func TestMounted(t *testing.T) {
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
mount := &Mount{
|
if err := Mount(sourcePath, targetPath, "none", "bind,ro"); err != nil {
|
||||||
Device: sourcePath,
|
|
||||||
Target: targetPath,
|
|
||||||
Type: "none",
|
|
||||||
Options: "bind,ro",
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := mount.Mount("/"); err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := mount.Unmount("/"); err != nil {
|
if err := Unmount(targetPath); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
|
@ -0,0 +1,9 @@
|
||||||
|
package mount
|
||||||
|
|
||||||
|
func mount(device, target, mType string, flag uintptr, data string) error {
|
||||||
|
panic("Not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmount(target string, flag int) error {
|
||||||
|
panic("Not implemented")
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package mount
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mount(device, target, mType string, flag uintptr, data string) error {
|
||||||
|
return syscall.Mount(device, target, mType, flag, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmount(target string, flag int) error {
|
||||||
|
return syscall.Unmount(target, flag)
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package mount
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
mountinfoFormat = "%d %d %d:%d %s %s %s - %s %s %s"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Represents one line from /proc/self/mountinfo
|
||||||
|
type procEntry struct {
|
||||||
|
id, parent, major, minor int
|
||||||
|
source, mountpoint, fstype, device string
|
||||||
|
vfsopts, opts string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse /proc/self/mountinfo because comparing Dev and ino does not work from bind mounts
|
||||||
|
func parseMountTable() ([]*procEntry, error) {
|
||||||
|
f, err := os.Open("/proc/self/mountinfo")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
s := bufio.NewScanner(f)
|
||||||
|
out := []*procEntry{}
|
||||||
|
for s.Scan() {
|
||||||
|
if err := s.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &procEntry{}
|
||||||
|
if _, err := fmt.Sscanf(s.Text(), mountinfoFormat,
|
||||||
|
&p.id, &p.parent, &p.major, &p.minor,
|
||||||
|
&p.source, &p.mountpoint, &p.vfsopts, &p.fstype,
|
||||||
|
&p.device, &p.opts); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out = append(out, p)
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
61
runtime.go
61
runtime.go
|
@ -788,67 +788,6 @@ func (runtime *Runtime) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *Runtime) getMounts(container *Container) ([]*graphdriver.Mount, error) {
|
|
||||||
// Generate additional bind mounts
|
|
||||||
envPath, err := container.EnvConfigPath()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
mounts := []*graphdriver.Mount{
|
|
||||||
{
|
|
||||||
Device: runtime.sysInitPath,
|
|
||||||
Target: "/.dockerinit",
|
|
||||||
Type: "none",
|
|
||||||
Options: "bind,ro",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Device: envPath,
|
|
||||||
Target: "/.dockerenv",
|
|
||||||
Type: "none",
|
|
||||||
Options: "bind,ro",
|
|
||||||
},
|
|
||||||
// In order to get a working DNS environment, mount bind (ro) the host's /etc/resolv.conf into the container
|
|
||||||
{
|
|
||||||
Device: container.ResolvConfPath,
|
|
||||||
Target: "/etc/resolv.conf",
|
|
||||||
Type: "none",
|
|
||||||
Options: "bind,ro",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if container.HostnamePath != "" && container.HostsPath != "" {
|
|
||||||
mounts = append(mounts,
|
|
||||||
&graphdriver.Mount{
|
|
||||||
Device: container.HostnamePath,
|
|
||||||
Target: "/etc/hostname",
|
|
||||||
Type: "none",
|
|
||||||
Options: "bind,ro",
|
|
||||||
},
|
|
||||||
&graphdriver.Mount{
|
|
||||||
Device: container.HostsPath,
|
|
||||||
Target: "/etc/hosts",
|
|
||||||
Type: "none",
|
|
||||||
Options: "bind,ro",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for r, v := range container.Volumes {
|
|
||||||
mountAs := "ro"
|
|
||||||
if container.VolumesRW[v] {
|
|
||||||
mountAs = "rw"
|
|
||||||
}
|
|
||||||
|
|
||||||
mounts = append(mounts,
|
|
||||||
&graphdriver.Mount{
|
|
||||||
Device: v,
|
|
||||||
Target: r,
|
|
||||||
Type: "none",
|
|
||||||
Options: fmt.Sprintf("bind,%s", mountAs),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return mounts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (runtime *Runtime) Mount(container *Container) error {
|
func (runtime *Runtime) Mount(container *Container) error {
|
||||||
dir, err := runtime.driver.Get(container.ID)
|
dir, err := runtime.driver.Get(container.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue