github.com/csfrancis/docker@v1.8.0-rc2/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 !config.NetworkDisabled && daemon.SystemConfig().IPv4ForwardingDisabled {
    70  		warnings = append(warnings, "IPv4 forwarding is disabled.")
    71  	}
    72  	if hostConfig == nil {
    73  		hostConfig = &runconfig.HostConfig{}
    74  	}
    75  	if hostConfig.SecurityOpt == nil {
    76  		hostConfig.SecurityOpt, err = daemon.GenerateSecurityOpt(hostConfig.IpcMode, hostConfig.PidMode)
    77  		if err != nil {
    78  			return nil, nil, err
    79  		}
    80  	}
    81  	if container, err = daemon.newContainer(name, config, imgID); err != nil {
    82  		return nil, nil, err
    83  	}
    84  	if err := daemon.Register(container); err != nil {
    85  		return nil, nil, err
    86  	}
    87  	if err := daemon.createRootfs(container); err != nil {
    88  		return nil, nil, err
    89  	}
    90  	if err := daemon.setHostConfig(container, hostConfig); err != nil {
    91  		return nil, nil, err
    92  	}
    93  	if err := container.Mount(); err != nil {
    94  		return nil, nil, err
    95  	}
    96  	defer container.Unmount()
    97  
    98  	for spec := range config.Volumes {
    99  		var (
   100  			name, destination string
   101  			parts             = strings.Split(spec, ":")
   102  		)
   103  		switch len(parts) {
   104  		case 2:
   105  			name, destination = parts[0], filepath.Clean(parts[1])
   106  		default:
   107  			name = stringid.GenerateRandomID()
   108  			destination = filepath.Clean(parts[0])
   109  		}
   110  		// Skip volumes for which we already have something mounted on that
   111  		// destination because of a --volume-from.
   112  		if container.isDestinationMounted(destination) {
   113  			continue
   114  		}
   115  		path, err := container.GetResourcePath(destination)
   116  		if err != nil {
   117  			return nil, nil, err
   118  		}
   119  
   120  		stat, err := os.Stat(path)
   121  		if err == nil && !stat.IsDir() {
   122  			return nil, nil, fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
   123  		}
   124  
   125  		v, err := createVolume(name, config.VolumeDriver)
   126  		if err != nil {
   127  			return nil, nil, err
   128  		}
   129  		if err := label.Relabel(v.Path(), container.MountLabel, "z"); err != nil {
   130  			return nil, nil, err
   131  		}
   132  
   133  		if err := container.copyImagePathContent(v, destination); err != nil {
   134  			return nil, nil, err
   135  		}
   136  
   137  		container.addMountPointWithVolume(destination, v, true)
   138  	}
   139  	if err := container.ToDisk(); err != nil {
   140  		logrus.Errorf("Error saving new container to disk: %v", err)
   141  		return nil, nil, err
   142  	}
   143  	container.LogEvent("create")
   144  	return container, warnings, nil
   145  }
   146  
   147  func (daemon *Daemon) GenerateSecurityOpt(ipcMode runconfig.IpcMode, pidMode runconfig.PidMode) ([]string, error) {
   148  	if ipcMode.IsHost() || pidMode.IsHost() {
   149  		return label.DisableSecOpt(), nil
   150  	}
   151  	if ipcContainer := ipcMode.Container(); ipcContainer != "" {
   152  		c, err := daemon.Get(ipcContainer)
   153  		if err != nil {
   154  			return nil, err
   155  		}
   156  
   157  		return label.DupSecOpt(c.ProcessLabel), nil
   158  	}
   159  	return nil, nil
   160  }