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