create.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package daemon
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. "github.com/docker/docker/graph"
  8. "github.com/docker/docker/image"
  9. "github.com/docker/docker/pkg/parsers"
  10. "github.com/docker/docker/pkg/stringid"
  11. "github.com/docker/docker/runconfig"
  12. "github.com/docker/libcontainer/label"
  13. )
  14. func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig) (string, []string, error) {
  15. warnings, err := daemon.verifyHostConfig(hostConfig)
  16. if err != nil {
  17. return "", warnings, err
  18. }
  19. // The check for a valid workdir path is made on the server rather than in the
  20. // client. This is because we don't know the type of path (Linux or Windows)
  21. // to validate on the client.
  22. if config.WorkingDir != "" && !filepath.IsAbs(config.WorkingDir) {
  23. return "", warnings, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir)
  24. }
  25. container, buildWarnings, err := daemon.Create(config, hostConfig, name)
  26. if err != nil {
  27. if daemon.Graph().IsNotExist(err, config.Image) {
  28. _, tag := parsers.ParseRepositoryTag(config.Image)
  29. if tag == "" {
  30. tag = graph.DEFAULTTAG
  31. }
  32. return "", warnings, fmt.Errorf("No such image: %s (tag: %s)", config.Image, tag)
  33. }
  34. return "", warnings, err
  35. }
  36. container.LogEvent("create")
  37. warnings = append(warnings, buildWarnings...)
  38. return container.ID, warnings, nil
  39. }
  40. // Create creates a new container from the given configuration with a given name.
  41. func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.HostConfig, name string) (*Container, []string, error) {
  42. var (
  43. container *Container
  44. warnings []string
  45. img *image.Image
  46. imgID string
  47. err error
  48. )
  49. if config.Image != "" {
  50. img, err = daemon.repositories.LookupImage(config.Image)
  51. if err != nil {
  52. return nil, nil, err
  53. }
  54. if err = img.CheckDepth(); err != nil {
  55. return nil, nil, err
  56. }
  57. imgID = img.ID
  58. }
  59. if warnings, err = daemon.mergeAndVerifyConfig(config, img); err != nil {
  60. return nil, nil, err
  61. }
  62. if !config.NetworkDisabled && daemon.SystemConfig().IPv4ForwardingDisabled {
  63. warnings = append(warnings, "IPv4 forwarding is disabled.\n")
  64. }
  65. if hostConfig == nil {
  66. hostConfig = &runconfig.HostConfig{}
  67. }
  68. if hostConfig.SecurityOpt == nil {
  69. hostConfig.SecurityOpt, err = daemon.GenerateSecurityOpt(hostConfig.IpcMode, hostConfig.PidMode)
  70. if err != nil {
  71. return nil, nil, err
  72. }
  73. }
  74. if container, err = daemon.newContainer(name, config, imgID); err != nil {
  75. return nil, nil, err
  76. }
  77. if err := daemon.Register(container); err != nil {
  78. return nil, nil, err
  79. }
  80. if err := daemon.createRootfs(container); err != nil {
  81. return nil, nil, err
  82. }
  83. if err := daemon.setHostConfig(container, hostConfig); err != nil {
  84. return nil, nil, err
  85. }
  86. if err := container.Mount(); err != nil {
  87. return nil, nil, err
  88. }
  89. defer container.Unmount()
  90. for spec := range config.Volumes {
  91. var (
  92. name, destination string
  93. parts = strings.Split(spec, ":")
  94. )
  95. switch len(parts) {
  96. case 2:
  97. name, destination = parts[0], filepath.Clean(parts[1])
  98. default:
  99. name = stringid.GenerateRandomID()
  100. destination = filepath.Clean(parts[0])
  101. }
  102. // Skip volumes for which we already have something mounted on that
  103. // destination because of a --volume-from.
  104. if container.isDestinationMounted(destination) {
  105. continue
  106. }
  107. path, err := container.GetResourcePath(destination)
  108. if err != nil {
  109. return nil, nil, err
  110. }
  111. stat, err := os.Stat(path)
  112. if err == nil && !stat.IsDir() {
  113. return nil, nil, fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
  114. }
  115. v, err := createVolume(name, config.VolumeDriver)
  116. if err != nil {
  117. return nil, nil, err
  118. }
  119. if err := label.Relabel(v.Path(), container.MountLabel, "z"); err != nil {
  120. return nil, nil, err
  121. }
  122. if err := container.copyImagePathContent(v, destination); err != nil {
  123. return nil, nil, err
  124. }
  125. container.addMountPointWithVolume(destination, v, true)
  126. }
  127. if err := container.ToDisk(); err != nil {
  128. return nil, nil, err
  129. }
  130. return container, warnings, nil
  131. }
  132. func (daemon *Daemon) GenerateSecurityOpt(ipcMode runconfig.IpcMode, pidMode runconfig.PidMode) ([]string, error) {
  133. if ipcMode.IsHost() || pidMode.IsHost() {
  134. return label.DisableSecOpt(), nil
  135. }
  136. if ipcContainer := ipcMode.Container(); ipcContainer != "" {
  137. c, err := daemon.Get(ipcContainer)
  138. if err != nil {
  139. return nil, err
  140. }
  141. return label.DupSecOpt(c.ProcessLabel), nil
  142. }
  143. return nil, nil
  144. }