github.com/Shopify/docker@v1.13.1/volume/local/local_unix.go (about)

     1  // +build linux freebsd solaris
     2  
     3  // Package local provides the default implementation for volumes. It
     4  // is used to mount data volume containers and directories local to
     5  // the host server.
     6  package local
     7  
     8  import (
     9  	"fmt"
    10  	"net"
    11  	"path/filepath"
    12  	"strings"
    13  
    14  	"github.com/pkg/errors"
    15  
    16  	"github.com/docker/docker/pkg/mount"
    17  )
    18  
    19  var (
    20  	oldVfsDir = filepath.Join("vfs", "dir")
    21  
    22  	validOpts = map[string]bool{
    23  		"type":   true, // specify the filesystem type for mount, e.g. nfs
    24  		"o":      true, // generic mount options
    25  		"device": true, // device to mount from
    26  	}
    27  )
    28  
    29  type optsConfig struct {
    30  	MountType   string
    31  	MountOpts   string
    32  	MountDevice string
    33  }
    34  
    35  func (o *optsConfig) String() string {
    36  	return fmt.Sprintf("type='%s' device='%s' o='%s'", o.MountType, o.MountDevice, o.MountOpts)
    37  }
    38  
    39  // scopedPath verifies that the path where the volume is located
    40  // is under Docker's root and the valid local paths.
    41  func (r *Root) scopedPath(realPath string) bool {
    42  	// Volumes path for Docker version >= 1.7
    43  	if strings.HasPrefix(realPath, filepath.Join(r.scope, volumesPathName)) && realPath != filepath.Join(r.scope, volumesPathName) {
    44  		return true
    45  	}
    46  
    47  	// Volumes path for Docker version < 1.7
    48  	if strings.HasPrefix(realPath, filepath.Join(r.scope, oldVfsDir)) {
    49  		return true
    50  	}
    51  
    52  	return false
    53  }
    54  
    55  func setOpts(v *localVolume, opts map[string]string) error {
    56  	if len(opts) == 0 {
    57  		return nil
    58  	}
    59  	if err := validateOpts(opts); err != nil {
    60  		return err
    61  	}
    62  
    63  	v.opts = &optsConfig{
    64  		MountType:   opts["type"],
    65  		MountOpts:   opts["o"],
    66  		MountDevice: opts["device"],
    67  	}
    68  	return nil
    69  }
    70  
    71  func (v *localVolume) mount() error {
    72  	if v.opts.MountDevice == "" {
    73  		return fmt.Errorf("missing device in volume options")
    74  	}
    75  	mountOpts := v.opts.MountOpts
    76  	if v.opts.MountType == "nfs" {
    77  		if addrValue := getAddress(v.opts.MountOpts); addrValue != "" && net.ParseIP(addrValue).To4() == nil {
    78  			ipAddr, err := net.ResolveIPAddr("ip", addrValue)
    79  			if err != nil {
    80  				return errors.Wrapf(err, "error resolving passed in nfs address")
    81  			}
    82  			mountOpts = strings.Replace(mountOpts, "addr="+addrValue, "addr="+ipAddr.String(), 1)
    83  		}
    84  	}
    85  	err := mount.Mount(v.opts.MountDevice, v.path, v.opts.MountType, mountOpts)
    86  	return errors.Wrapf(err, "error while mounting volume with options: %s", v.opts)
    87  }