create.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. package daemon
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/Sirupsen/logrus"
  6. "github.com/docker/docker/container"
  7. "github.com/docker/docker/errors"
  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. "github.com/docker/docker/runconfig"
  13. volumestore "github.com/docker/docker/volume/store"
  14. "github.com/docker/engine-api/types"
  15. containertypes "github.com/docker/engine-api/types/container"
  16. networktypes "github.com/docker/engine-api/types/network"
  17. "github.com/opencontainers/runc/libcontainer/label"
  18. )
  19. // CreateManagedContainer creates a container that is managed by a Service
  20. func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) {
  21. return daemon.containerCreate(params, true, validateHostname)
  22. }
  23. // ContainerCreate creates a regular container
  24. func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) {
  25. return daemon.containerCreate(params, false, validateHostname)
  26. }
  27. func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool, validateHostname bool) (types.ContainerCreateResponse, error) {
  28. if params.Config == nil {
  29. return types.ContainerCreateResponse{}, fmt.Errorf("Config cannot be empty in order to create a container")
  30. }
  31. warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false, validateHostname)
  32. if err != nil {
  33. return types.ContainerCreateResponse{Warnings: warnings}, err
  34. }
  35. err = daemon.verifyNetworkingConfig(params.NetworkingConfig)
  36. if err != nil {
  37. return types.ContainerCreateResponse{}, err
  38. }
  39. if params.HostConfig == nil {
  40. params.HostConfig = &containertypes.HostConfig{}
  41. }
  42. err = daemon.adaptContainerSettings(params.HostConfig, params.AdjustCPUShares)
  43. if err != nil {
  44. return types.ContainerCreateResponse{Warnings: warnings}, err
  45. }
  46. container, err := daemon.create(params, managed)
  47. if err != nil {
  48. return types.ContainerCreateResponse{Warnings: warnings}, daemon.imageNotExistToErrcode(err)
  49. }
  50. return types.ContainerCreateResponse{ID: container.ID, Warnings: warnings}, nil
  51. }
  52. // Create creates a new container from the given configuration with a given name.
  53. func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) (retC *container.Container, retErr error) {
  54. var (
  55. container *container.Container
  56. img *image.Image
  57. imgID image.ID
  58. err error
  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. if err := daemon.mergeAndVerifyConfig(params.Config, img); err != nil {
  68. return nil, err
  69. }
  70. if err := daemon.mergeAndVerifyLogConfig(&params.HostConfig.LogConfig); err != nil {
  71. return nil, err
  72. }
  73. if container, err = daemon.newContainer(params.Name, params.Config, imgID, managed); err != nil {
  74. return nil, err
  75. }
  76. defer func() {
  77. if retErr != nil {
  78. if err := daemon.cleanupContainer(container, true); err != nil {
  79. logrus.Errorf("failed to cleanup container on create error: %v", err)
  80. }
  81. }
  82. }()
  83. if err := daemon.setSecurityOptions(container, params.HostConfig); err != nil {
  84. return nil, err
  85. }
  86. container.HostConfig.StorageOpt = params.HostConfig.StorageOpt
  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. rootUID, rootGID, err := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps)
  92. if err != nil {
  93. return nil, err
  94. }
  95. if err := idtools.MkdirAs(container.Root, 0700, rootUID, rootGID); err != nil {
  96. return nil, err
  97. }
  98. if err := daemon.setHostConfig(container, params.HostConfig); err != nil {
  99. return nil, err
  100. }
  101. defer func() {
  102. if retErr != nil {
  103. if err := daemon.removeMountPoints(container, true); err != nil {
  104. logrus.Error(err)
  105. }
  106. }
  107. }()
  108. if err := daemon.createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig); err != nil {
  109. return nil, err
  110. }
  111. var endpointsConfigs map[string]*networktypes.EndpointSettings
  112. if params.NetworkingConfig != nil {
  113. endpointsConfigs = params.NetworkingConfig.EndpointsConfig
  114. }
  115. // Make sure NetworkMode has an acceptable value. We do this to ensure
  116. // backwards API compatibility.
  117. container.HostConfig = runconfig.SetDefaultNetModeIfBlank(container.HostConfig)
  118. if err := daemon.updateContainerNetworkSettings(container, endpointsConfigs); err != nil {
  119. return nil, err
  120. }
  121. if err := container.ToDisk(); err != nil {
  122. logrus.Errorf("Error saving new container to disk: %v", err)
  123. return nil, err
  124. }
  125. if err := daemon.Register(container); err != nil {
  126. return nil, err
  127. }
  128. daemon.LogContainerEvent(container, "create")
  129. return container, nil
  130. }
  131. func (daemon *Daemon) generateSecurityOpt(ipcMode containertypes.IpcMode, pidMode containertypes.PidMode, privileged bool) ([]string, error) {
  132. if ipcMode.IsHost() || pidMode.IsHost() || privileged {
  133. return label.DisableSecOpt(), nil
  134. }
  135. var ipcLabel []string
  136. var pidLabel []string
  137. ipcContainer := ipcMode.Container()
  138. pidContainer := pidMode.Container()
  139. if ipcContainer != "" {
  140. c, err := daemon.GetContainer(ipcContainer)
  141. if err != nil {
  142. return nil, err
  143. }
  144. ipcLabel = label.DupSecOpt(c.ProcessLabel)
  145. if pidContainer == "" {
  146. return ipcLabel, err
  147. }
  148. }
  149. if pidContainer != "" {
  150. c, err := daemon.GetContainer(pidContainer)
  151. if err != nil {
  152. return nil, err
  153. }
  154. pidLabel = label.DupSecOpt(c.ProcessLabel)
  155. if ipcContainer == "" {
  156. return pidLabel, err
  157. }
  158. }
  159. if pidLabel != nil && ipcLabel != nil {
  160. for i := 0; i < len(pidLabel); i++ {
  161. if pidLabel[i] != ipcLabel[i] {
  162. return nil, fmt.Errorf("--ipc and --pid containers SELinux labels aren't the same")
  163. }
  164. }
  165. return pidLabel, nil
  166. }
  167. return nil, nil
  168. }
  169. func (daemon *Daemon) setRWLayer(container *container.Container) error {
  170. var layerID layer.ChainID
  171. if container.ImageID != "" {
  172. img, err := daemon.imageStore.Get(container.ImageID)
  173. if err != nil {
  174. return err
  175. }
  176. layerID = img.RootFS.ChainID()
  177. }
  178. rwLayer, err := daemon.layerStore.CreateRWLayer(container.ID, layerID, container.MountLabel, daemon.setupInitLayer, container.HostConfig.StorageOpt)
  179. if err != nil {
  180. return err
  181. }
  182. container.RWLayer = rwLayer
  183. return nil
  184. }
  185. // VolumeCreate creates a volume with the specified name, driver, and opts
  186. // This is called directly from the remote API
  187. func (daemon *Daemon) VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error) {
  188. if name == "" {
  189. name = stringid.GenerateNonCryptoID()
  190. }
  191. v, err := daemon.volumes.Create(name, driverName, opts, labels)
  192. if err != nil {
  193. if volumestore.IsNameConflict(err) {
  194. return nil, fmt.Errorf("A volume named %s already exists. Choose a different volume name.", name)
  195. }
  196. return nil, err
  197. }
  198. daemon.LogVolumeEvent(v.Name(), "create", map[string]string{"driver": v.DriverName()})
  199. apiV := volumeToAPIType(v)
  200. apiV.Mountpoint = v.Path()
  201. return apiV, nil
  202. }
  203. func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *image.Image) error {
  204. if img != nil && img.Config != nil {
  205. if err := merge(config, img.Config); err != nil {
  206. return err
  207. }
  208. }
  209. if len(config.Entrypoint) == 0 && len(config.Cmd) == 0 {
  210. return fmt.Errorf("No command specified")
  211. }
  212. return nil
  213. }
  214. // Checks if the client set configurations for more than one network while creating a container
  215. func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingConfig) error {
  216. if nwConfig == nil || len(nwConfig.EndpointsConfig) <= 1 {
  217. return nil
  218. }
  219. l := make([]string, 0, len(nwConfig.EndpointsConfig))
  220. for k := range nwConfig.EndpointsConfig {
  221. l = append(l, k)
  222. }
  223. err := fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", "))
  224. return errors.NewBadRequestError(err)
  225. }