github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/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.cleanupContainer(container, true); err != nil {
    78  				logrus.Errorf("failed to cleanup container on create error: %v", err)
    79  			}
    80  		}
    81  	}()
    82  
    83  	if err := daemon.setSecurityOptions(container, params.HostConfig); err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	container.HostConfig.StorageOpt = params.HostConfig.StorageOpt
    88  
    89  	// Set RWLayer for container after mount labels have been set
    90  	if err := daemon.setRWLayer(container); err != nil {
    91  		return nil, err
    92  	}
    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.ToDisk(); err != nil {
   127  		logrus.Errorf("Error saving new container to disk: %v", err)
   128  		return nil, err
   129  	}
   130  	if err := daemon.Register(container); err != nil {
   131  		return nil, err
   132  	}
   133  	daemon.LogContainerEvent(container, "create")
   134  	return container, nil
   135  }
   136  
   137  func (daemon *Daemon) generateSecurityOpt(ipcMode containertypes.IpcMode, pidMode containertypes.PidMode) ([]string, error) {
   138  	if ipcMode.IsHost() || pidMode.IsHost() {
   139  		return label.DisableSecOpt(), nil
   140  	}
   141  	if ipcContainer := ipcMode.Container(); ipcContainer != "" {
   142  		c, err := daemon.GetContainer(ipcContainer)
   143  		if err != nil {
   144  			return nil, err
   145  		}
   146  
   147  		return label.DupSecOpt(c.ProcessLabel), nil
   148  	}
   149  	return nil, nil
   150  }
   151  
   152  func (daemon *Daemon) setRWLayer(container *container.Container) error {
   153  	var layerID layer.ChainID
   154  	if container.ImageID != "" {
   155  		img, err := daemon.imageStore.Get(container.ImageID)
   156  		if err != nil {
   157  			return err
   158  		}
   159  		layerID = img.RootFS.ChainID()
   160  	}
   161  	rwLayer, err := daemon.layerStore.CreateRWLayer(container.ID, layerID, container.MountLabel, daemon.setupInitLayer, container.HostConfig.StorageOpt)
   162  	if err != nil {
   163  		return err
   164  	}
   165  	container.RWLayer = rwLayer
   166  
   167  	return nil
   168  }
   169  
   170  // VolumeCreate creates a volume with the specified name, driver, and opts
   171  // This is called directly from the remote API
   172  func (daemon *Daemon) VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error) {
   173  	if name == "" {
   174  		name = stringid.GenerateNonCryptoID()
   175  	}
   176  
   177  	v, err := daemon.volumes.Create(name, driverName, opts, labels)
   178  	if err != nil {
   179  		if volumestore.IsNameConflict(err) {
   180  			return nil, fmt.Errorf("A volume named %s already exists. Choose a different volume name.", name)
   181  		}
   182  		return nil, err
   183  	}
   184  
   185  	daemon.LogVolumeEvent(v.Name(), "create", map[string]string{"driver": v.DriverName()})
   186  	return volumeToAPIType(v), nil
   187  }