github.com/jogo/docker@v1.7.0-rc1/daemon/create.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/docker/docker/graph"
    10  	"github.com/docker/docker/image"
    11  	"github.com/docker/docker/pkg/parsers"
    12  	"github.com/docker/docker/pkg/stringid"
    13  	"github.com/docker/docker/runconfig"
    14  	"github.com/docker/libcontainer/label"
    15  )
    16  
    17  func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig) (string, []string, error) {
    18  	warnings, err := daemon.verifyHostConfig(hostConfig)
    19  	if err != nil {
    20  		return "", warnings, err
    21  	}
    22  
    23  	// The check for a valid workdir path is made on the server rather than in the
    24  	// client. This is because we don't know the type of path (Linux or Windows)
    25  	// to validate on the client.
    26  	if config.WorkingDir != "" && !filepath.IsAbs(config.WorkingDir) {
    27  		return "", warnings, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir)
    28  	}
    29  
    30  	container, buildWarnings, err := daemon.Create(config, hostConfig, name)
    31  	if err != nil {
    32  		if daemon.Graph().IsNotExist(err, config.Image) {
    33  			_, tag := parsers.ParseRepositoryTag(config.Image)
    34  			if tag == "" {
    35  				tag = graph.DEFAULTTAG
    36  			}
    37  			return "", warnings, fmt.Errorf("No such image: %s (tag: %s)", config.Image, tag)
    38  		}
    39  		return "", warnings, err
    40  	}
    41  
    42  	container.LogEvent("create")
    43  	warnings = append(warnings, buildWarnings...)
    44  
    45  	return container.ID, warnings, nil
    46  }
    47  
    48  // Create creates a new container from the given configuration with a given name.
    49  func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.HostConfig, name string) (*Container, []string, error) {
    50  	var (
    51  		container *Container
    52  		warnings  []string
    53  		img       *image.Image
    54  		imgID     string
    55  		err       error
    56  	)
    57  
    58  	if config.Image != "" {
    59  		img, err = daemon.repositories.LookupImage(config.Image)
    60  		if err != nil {
    61  			return nil, nil, err
    62  		}
    63  		if err = img.CheckDepth(); err != nil {
    64  			return nil, nil, err
    65  		}
    66  		imgID = img.ID
    67  	}
    68  
    69  	if warnings, err = daemon.mergeAndVerifyConfig(config, img); err != nil {
    70  		return nil, nil, err
    71  	}
    72  	if !config.NetworkDisabled && daemon.SystemConfig().IPv4ForwardingDisabled {
    73  		warnings = append(warnings, "IPv4 forwarding is disabled.\n")
    74  	}
    75  	if hostConfig == nil {
    76  		hostConfig = &runconfig.HostConfig{}
    77  	}
    78  	if hostConfig.SecurityOpt == nil {
    79  		hostConfig.SecurityOpt, err = daemon.GenerateSecurityOpt(hostConfig.IpcMode, hostConfig.PidMode)
    80  		if err != nil {
    81  			return nil, nil, err
    82  		}
    83  	}
    84  	if container, err = daemon.newContainer(name, config, imgID); err != nil {
    85  		return nil, nil, err
    86  	}
    87  	if err := daemon.Register(container); err != nil {
    88  		return nil, nil, err
    89  	}
    90  	if err := daemon.createRootfs(container); err != nil {
    91  		return nil, nil, err
    92  	}
    93  	if err := daemon.setHostConfig(container, hostConfig); err != nil {
    94  		return nil, nil, err
    95  	}
    96  	if err := container.Mount(); err != nil {
    97  		return nil, nil, err
    98  	}
    99  	defer container.Unmount()
   100  
   101  	for spec := range config.Volumes {
   102  		var (
   103  			name, destination string
   104  			parts             = strings.Split(spec, ":")
   105  		)
   106  		switch len(parts) {
   107  		case 2:
   108  			name, destination = parts[0], filepath.Clean(parts[1])
   109  		default:
   110  			name = stringid.GenerateRandomID()
   111  			destination = filepath.Clean(parts[0])
   112  		}
   113  		// Skip volumes for which we already have something mounted on that
   114  		// destination because of a --volume-from.
   115  		if container.isDestinationMounted(destination) {
   116  			continue
   117  		}
   118  		path, err := container.GetResourcePath(destination)
   119  		if err != nil {
   120  			return nil, nil, err
   121  		}
   122  
   123  		stat, err := os.Stat(path)
   124  		if err == nil && !stat.IsDir() {
   125  			return nil, nil, fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
   126  		}
   127  
   128  		v, err := createVolume(name, config.VolumeDriver)
   129  		if err != nil {
   130  			return nil, nil, err
   131  		}
   132  		if err := label.Relabel(v.Path(), container.MountLabel, "z"); err != nil {
   133  			return nil, nil, err
   134  		}
   135  
   136  		if err := container.copyImagePathContent(v, destination); err != nil {
   137  			return nil, nil, err
   138  		}
   139  
   140  		container.addMountPointWithVolume(destination, v, true)
   141  	}
   142  	if err := container.ToDisk(); err != nil {
   143  		return nil, nil, err
   144  	}
   145  	return container, warnings, nil
   146  }
   147  
   148  func (daemon *Daemon) GenerateSecurityOpt(ipcMode runconfig.IpcMode, pidMode runconfig.PidMode) ([]string, error) {
   149  	if ipcMode.IsHost() || pidMode.IsHost() {
   150  		return label.DisableSecOpt(), nil
   151  	}
   152  	if ipcContainer := ipcMode.Container(); ipcContainer != "" {
   153  		c, err := daemon.Get(ipcContainer)
   154  		if err != nil {
   155  			return nil, err
   156  		}
   157  
   158  		return label.DupSecOpt(c.ProcessLabel), nil
   159  	}
   160  	return nil, nil
   161  }