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 }