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 }