github.com/uriddle/docker@v0.0.0-20210926094723-4072e6aeb013/daemon/create.go (about)

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