github.com/torfuzx/docker@v1.8.1/daemon/create.go (about)

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