create.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package daemon
  2. import (
  3. "fmt"
  4. "github.com/Sirupsen/logrus"
  5. "github.com/docker/docker/container"
  6. "github.com/docker/docker/image"
  7. "github.com/docker/docker/layer"
  8. "github.com/docker/docker/pkg/idtools"
  9. "github.com/docker/docker/pkg/stringid"
  10. "github.com/docker/docker/runconfig"
  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. // ContainerCreate creates a container.
  18. func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types.ContainerCreateResponse, error) {
  19. if params.Config == nil {
  20. return types.ContainerCreateResponse{}, fmt.Errorf("Config cannot be empty in order to create a container")
  21. }
  22. warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false)
  23. if err != nil {
  24. return types.ContainerCreateResponse{Warnings: warnings}, err
  25. }
  26. err = daemon.verifyNetworkingConfig(params.NetworkingConfig)
  27. if err != nil {
  28. return types.ContainerCreateResponse{}, err
  29. }
  30. if params.HostConfig == nil {
  31. params.HostConfig = &containertypes.HostConfig{}
  32. }
  33. err = daemon.adaptContainerSettings(params.HostConfig, params.AdjustCPUShares)
  34. if err != nil {
  35. return types.ContainerCreateResponse{Warnings: warnings}, err
  36. }
  37. container, err := daemon.create(params)
  38. if err != nil {
  39. return types.ContainerCreateResponse{Warnings: warnings}, daemon.imageNotExistToErrcode(err)
  40. }
  41. return types.ContainerCreateResponse{ID: container.ID, Warnings: warnings}, nil
  42. }
  43. // Create creates a new container from the given configuration with a given name.
  44. func (daemon *Daemon) create(params types.ContainerCreateConfig) (retC *container.Container, retErr error) {
  45. var (
  46. container *container.Container
  47. img *image.Image
  48. imgID image.ID
  49. err error
  50. )
  51. if params.Config.Image != "" {
  52. img, err = daemon.GetImage(params.Config.Image)
  53. if err != nil {
  54. return nil, err
  55. }
  56. imgID = img.ID()
  57. }
  58. if err := daemon.mergeAndVerifyConfig(params.Config, img); err != nil {
  59. return nil, err
  60. }
  61. if err := daemon.mergeAndVerifyLogConfig(&params.HostConfig.LogConfig); err != nil {
  62. return nil, err
  63. }
  64. if container, err = daemon.newContainer(params.Name, params.Config, imgID); err != nil {
  65. return nil, err
  66. }
  67. defer func() {
  68. if retErr != nil {
  69. if err := daemon.cleanupContainer(container, true); err != nil {
  70. logrus.Errorf("failed to cleanup container on create error: %v", err)
  71. }
  72. }
  73. }()
  74. if err := daemon.setSecurityOptions(container, params.HostConfig); err != nil {
  75. return nil, err
  76. }
  77. container.HostConfig.StorageOpt = params.HostConfig.StorageOpt
  78. // Set RWLayer for container after mount labels have been set
  79. if err := daemon.setRWLayer(container); err != nil {
  80. return nil, err
  81. }
  82. rootUID, rootGID, err := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps)
  83. if err != nil {
  84. return nil, err
  85. }
  86. if err := idtools.MkdirAs(container.Root, 0700, rootUID, rootGID); err != nil {
  87. return nil, err
  88. }
  89. if err := daemon.setHostConfig(container, params.HostConfig); err != nil {
  90. return nil, err
  91. }
  92. defer func() {
  93. if retErr != nil {
  94. if err := daemon.removeMountPoints(container, true); err != nil {
  95. logrus.Error(err)
  96. }
  97. }
  98. }()
  99. if err := daemon.createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig); err != nil {
  100. return nil, err
  101. }
  102. var endpointsConfigs map[string]*networktypes.EndpointSettings
  103. if params.NetworkingConfig != nil {
  104. endpointsConfigs = params.NetworkingConfig.EndpointsConfig
  105. }
  106. // Make sure NetworkMode has an acceptable value. We do this to ensure
  107. // backwards API compatibility.
  108. container.HostConfig = runconfig.SetDefaultNetModeIfBlank(container.HostConfig)
  109. if err := daemon.updateContainerNetworkSettings(container, endpointsConfigs); err != nil {
  110. return nil, err
  111. }
  112. if err := container.ToDisk(); err != nil {
  113. logrus.Errorf("Error saving new container to disk: %v", err)
  114. return nil, err
  115. }
  116. if err := daemon.Register(container); err != nil {
  117. return nil, err
  118. }
  119. daemon.LogContainerEvent(container, "create")
  120. return container, nil
  121. }
  122. func (daemon *Daemon) generateSecurityOpt(ipcMode containertypes.IpcMode, pidMode containertypes.PidMode, privileged bool) ([]string, error) {
  123. if ipcMode.IsHost() || pidMode.IsHost() || privileged {
  124. return label.DisableSecOpt(), nil
  125. }
  126. var ipcLabel []string
  127. var pidLabel []string
  128. ipcContainer := ipcMode.Container()
  129. pidContainer := pidMode.Container()
  130. if ipcContainer != "" {
  131. c, err := daemon.GetContainer(ipcContainer)
  132. if err != nil {
  133. return nil, err
  134. }
  135. ipcLabel = label.DupSecOpt(c.ProcessLabel)
  136. if pidContainer == "" {
  137. return ipcLabel, err
  138. }
  139. }
  140. if pidContainer != "" {
  141. c, err := daemon.GetContainer(pidContainer)
  142. if err != nil {
  143. return nil, err
  144. }
  145. pidLabel = label.DupSecOpt(c.ProcessLabel)
  146. if ipcContainer == "" {
  147. return pidLabel, err
  148. }
  149. }
  150. if pidLabel != nil && ipcLabel != nil {
  151. for i := 0; i < len(pidLabel); i++ {
  152. if pidLabel[i] != ipcLabel[i] {
  153. return nil, fmt.Errorf("--ipc and --pid containers SELinux labels aren't the same")
  154. }
  155. }
  156. return pidLabel, nil
  157. }
  158. return nil, nil
  159. }
  160. func (daemon *Daemon) setRWLayer(container *container.Container) error {
  161. var layerID layer.ChainID
  162. if container.ImageID != "" {
  163. img, err := daemon.imageStore.Get(container.ImageID)
  164. if err != nil {
  165. return err
  166. }
  167. layerID = img.RootFS.ChainID()
  168. }
  169. rwLayer, err := daemon.layerStore.CreateRWLayer(container.ID, layerID, container.MountLabel, daemon.setupInitLayer, container.HostConfig.StorageOpt)
  170. if err != nil {
  171. return err
  172. }
  173. container.RWLayer = rwLayer
  174. return nil
  175. }
  176. // VolumeCreate creates a volume with the specified name, driver, and opts
  177. // This is called directly from the remote API
  178. func (daemon *Daemon) VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error) {
  179. if name == "" {
  180. name = stringid.GenerateNonCryptoID()
  181. }
  182. v, err := daemon.volumes.Create(name, driverName, opts, labels)
  183. if err != nil {
  184. if volumestore.IsNameConflict(err) {
  185. return nil, fmt.Errorf("A volume named %s already exists. Choose a different volume name.", name)
  186. }
  187. return nil, err
  188. }
  189. daemon.LogVolumeEvent(v.Name(), "create", map[string]string{"driver": v.DriverName()})
  190. apiV := volumeToAPIType(v)
  191. apiV.Mountpoint = v.Path()
  192. return apiV, nil
  193. }