github.com/boynux/docker@v1.11.0-rc4/daemon/create.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/Sirupsen/logrus"
     7  	"github.com/docker/docker/container"
     8  	"github.com/docker/docker/image"
     9  	"github.com/docker/docker/layer"
    10  	"github.com/docker/docker/pkg/idtools"
    11  	"github.com/docker/docker/pkg/stringid"
    12  	volumestore "github.com/docker/docker/volume/store"
    13  	"github.com/docker/engine-api/types"
    14  	containertypes "github.com/docker/engine-api/types/container"
    15  	networktypes "github.com/docker/engine-api/types/network"
    16  	"github.com/opencontainers/runc/libcontainer/label"
    17  )
    18  
    19  // ContainerCreate creates a container.
    20  func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types.ContainerCreateResponse, error) {
    21  	if params.Config == nil {
    22  		return types.ContainerCreateResponse{}, fmt.Errorf("Config cannot be empty in order to create a container")
    23  	}
    24  
    25  	warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false)
    26  	if err != nil {
    27  		return types.ContainerCreateResponse{Warnings: warnings}, err
    28  	}
    29  
    30  	err = daemon.verifyNetworkingConfig(params.NetworkingConfig)
    31  	if err != nil {
    32  		return types.ContainerCreateResponse{}, err
    33  	}
    34  
    35  	if params.HostConfig == nil {
    36  		params.HostConfig = &containertypes.HostConfig{}
    37  	}
    38  	err = daemon.adaptContainerSettings(params.HostConfig, params.AdjustCPUShares)
    39  	if err != nil {
    40  		return types.ContainerCreateResponse{Warnings: warnings}, err
    41  	}
    42  
    43  	container, err := daemon.create(params)
    44  	if err != nil {
    45  		return types.ContainerCreateResponse{Warnings: warnings}, daemon.imageNotExistToErrcode(err)
    46  	}
    47  
    48  	return types.ContainerCreateResponse{ID: container.ID, Warnings: warnings}, nil
    49  }
    50  
    51  // Create creates a new container from the given configuration with a given name.
    52  func (daemon *Daemon) create(params types.ContainerCreateConfig) (retC *container.Container, retErr error) {
    53  	var (
    54  		container *container.Container
    55  		img       *image.Image
    56  		imgID     image.ID
    57  		err       error
    58  	)
    59  
    60  	if params.Config.Image != "" {
    61  		img, err = daemon.GetImage(params.Config.Image)
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  		imgID = img.ID()
    66  	}
    67  
    68  	if err := daemon.mergeAndVerifyConfig(params.Config, img); err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	if container, err = daemon.newContainer(params.Name, params.Config, imgID); err != nil {
    73  		return nil, err
    74  	}
    75  	defer func() {
    76  		if retErr != nil {
    77  			if err := daemon.ContainerRm(container.ID, &types.ContainerRmConfig{ForceRemove: true}); err != nil {
    78  				logrus.Errorf("Clean up Error! Cannot destroy container %s: %v", container.ID, err)
    79  			}
    80  		}
    81  	}()
    82  
    83  	if err := daemon.setSecurityOptions(container, params.HostConfig); err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	// Set RWLayer for container after mount labels have been set
    88  	if err := daemon.setRWLayer(container); err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	if err := daemon.Register(container); err != nil {
    93  		return nil, err
    94  	}
    95  	rootUID, rootGID, err := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	if err := idtools.MkdirAs(container.Root, 0700, rootUID, rootGID); err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	if err := daemon.setHostConfig(container, params.HostConfig); err != nil {
   104  		return nil, err
   105  	}
   106  	defer func() {
   107  		if retErr != nil {
   108  			if err := daemon.removeMountPoints(container, true); err != nil {
   109  				logrus.Error(err)
   110  			}
   111  		}
   112  	}()
   113  
   114  	if err := daemon.createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig); err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	var endpointsConfigs map[string]*networktypes.EndpointSettings
   119  	if params.NetworkingConfig != nil {
   120  		endpointsConfigs = params.NetworkingConfig.EndpointsConfig
   121  	}
   122  
   123  	if err := daemon.updateContainerNetworkSettings(container, endpointsConfigs); err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	if err := container.ToDiskLocking(); err != nil {
   128  		logrus.Errorf("Error saving new container to disk: %v", err)
   129  		return nil, err
   130  	}
   131  	daemon.LogContainerEvent(container, "create")
   132  	return container, nil
   133  }
   134  
   135  func (daemon *Daemon) generateSecurityOpt(ipcMode containertypes.IpcMode, pidMode containertypes.PidMode) ([]string, error) {
   136  	if ipcMode.IsHost() || pidMode.IsHost() {
   137  		return label.DisableSecOpt(), nil
   138  	}
   139  	if ipcContainer := ipcMode.Container(); ipcContainer != "" {
   140  		c, err := daemon.GetContainer(ipcContainer)
   141  		if err != nil {
   142  			return nil, err
   143  		}
   144  
   145  		return label.DupSecOpt(c.ProcessLabel), nil
   146  	}
   147  	return nil, nil
   148  }
   149  
   150  func (daemon *Daemon) setRWLayer(container *container.Container) error {
   151  	var layerID layer.ChainID
   152  	if container.ImageID != "" {
   153  		img, err := daemon.imageStore.Get(container.ImageID)
   154  		if err != nil {
   155  			return err
   156  		}
   157  		layerID = img.RootFS.ChainID()
   158  	}
   159  	rwLayer, err := daemon.layerStore.CreateRWLayer(container.ID, layerID, container.MountLabel, daemon.setupInitLayer)
   160  	if err != nil {
   161  		return err
   162  	}
   163  	container.RWLayer = rwLayer
   164  
   165  	return nil
   166  }
   167  
   168  // VolumeCreate creates a volume with the specified name, driver, and opts
   169  // This is called directly from the remote API
   170  func (daemon *Daemon) VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error) {
   171  	if name == "" {
   172  		name = stringid.GenerateNonCryptoID()
   173  	}
   174  
   175  	v, err := daemon.volumes.Create(name, driverName, opts, labels)
   176  	if err != nil {
   177  		if volumestore.IsNameConflict(err) {
   178  			return nil, fmt.Errorf("A volume named %s already exists. Choose a different volume name.", name)
   179  		}
   180  		return nil, err
   181  	}
   182  
   183  	daemon.LogVolumeEvent(v.Name(), "create", map[string]string{"driver": v.DriverName()})
   184  	return volumeToAPIType(v), nil
   185  }