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 }