github.com/alexandrev/docker@v1.9.0/daemon/create.go (about) 1 package daemon 2 3 import ( 4 "strings" 5 6 "github.com/Sirupsen/logrus" 7 "github.com/docker/docker/api/types" 8 derr "github.com/docker/docker/errors" 9 "github.com/docker/docker/graph/tags" 10 "github.com/docker/docker/image" 11 "github.com/docker/docker/pkg/parsers" 12 "github.com/docker/docker/pkg/stringid" 13 "github.com/docker/docker/runconfig" 14 "github.com/docker/docker/volume" 15 "github.com/opencontainers/runc/libcontainer/label" 16 ) 17 18 // ContainerCreate takes configs and creates a container. 19 func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig, adjustCPUShares bool) (types.ContainerCreateResponse, error) { 20 if config == nil { 21 return types.ContainerCreateResponse{}, derr.ErrorCodeEmptyConfig 22 } 23 24 warnings, err := daemon.verifyContainerSettings(hostConfig, config) 25 if err != nil { 26 return types.ContainerCreateResponse{"", warnings}, err 27 } 28 29 daemon.adaptContainerSettings(hostConfig, adjustCPUShares) 30 31 container, err := daemon.Create(config, hostConfig, name) 32 if err != nil { 33 if daemon.Graph().IsNotExist(err, config.Image) { 34 if strings.Contains(config.Image, "@") { 35 return types.ContainerCreateResponse{"", warnings}, derr.ErrorCodeNoSuchImageHash.WithArgs(config.Image) 36 } 37 img, tag := parsers.ParseRepositoryTag(config.Image) 38 if tag == "" { 39 tag = tags.DefaultTag 40 } 41 return types.ContainerCreateResponse{"", warnings}, derr.ErrorCodeNoSuchImageTag.WithArgs(img, tag) 42 } 43 return types.ContainerCreateResponse{"", warnings}, err 44 } 45 46 return types.ContainerCreateResponse{container.ID, warnings}, nil 47 } 48 49 // Create creates a new container from the given configuration with a given name. 50 func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.HostConfig, name string) (retC *Container, retErr error) { 51 var ( 52 container *Container 53 img *image.Image 54 imgID string 55 err error 56 ) 57 58 if config.Image != "" { 59 img, err = daemon.repositories.LookupImage(config.Image) 60 if err != nil { 61 return nil, err 62 } 63 if err = daemon.graph.CheckDepth(img); err != nil { 64 return nil, err 65 } 66 imgID = img.ID 67 } 68 69 if err := daemon.mergeAndVerifyConfig(config, img); err != nil { 70 return nil, err 71 } 72 73 if hostConfig == nil { 74 hostConfig = &runconfig.HostConfig{} 75 } 76 if hostConfig.SecurityOpt == nil { 77 hostConfig.SecurityOpt, err = daemon.generateSecurityOpt(hostConfig.IpcMode, hostConfig.PidMode) 78 if err != nil { 79 return nil, err 80 } 81 } 82 if container, err = daemon.newContainer(name, config, imgID); err != nil { 83 return nil, err 84 } 85 defer func() { 86 if retErr != nil { 87 if err := daemon.rm(container, false); err != nil { 88 logrus.Errorf("Clean up Error! Cannot destroy container %s: %v", container.ID, err) 89 } 90 } 91 }() 92 93 if err := daemon.Register(container); err != nil { 94 return nil, err 95 } 96 if err := daemon.createRootfs(container); err != nil { 97 return nil, err 98 } 99 if err := daemon.setHostConfig(container, hostConfig); err != nil { 100 return nil, err 101 } 102 defer func() { 103 if retErr != nil { 104 if err := container.removeMountPoints(true); err != nil { 105 logrus.Error(err) 106 } 107 } 108 }() 109 if err := container.Mount(); err != nil { 110 return nil, err 111 } 112 defer container.Unmount() 113 114 if err := createContainerPlatformSpecificSettings(container, config, hostConfig, img); err != nil { 115 return nil, err 116 } 117 118 if err := container.toDiskLocking(); err != nil { 119 logrus.Errorf("Error saving new container to disk: %v", err) 120 return nil, err 121 } 122 container.logEvent("create") 123 return container, nil 124 } 125 126 func (daemon *Daemon) generateSecurityOpt(ipcMode runconfig.IpcMode, pidMode runconfig.PidMode) ([]string, error) { 127 if ipcMode.IsHost() || pidMode.IsHost() { 128 return label.DisableSecOpt(), nil 129 } 130 if ipcContainer := ipcMode.Container(); ipcContainer != "" { 131 c, err := daemon.Get(ipcContainer) 132 if err != nil { 133 return nil, err 134 } 135 136 return label.DupSecOpt(c.ProcessLabel), nil 137 } 138 return nil, nil 139 } 140 141 // VolumeCreate creates a volume with the specified name, driver, and opts 142 // This is called directly from the remote API 143 func (daemon *Daemon) VolumeCreate(name, driverName string, opts map[string]string) (*types.Volume, error) { 144 if name == "" { 145 name = stringid.GenerateNonCryptoID() 146 } 147 148 v, err := daemon.volumes.Create(name, driverName, opts) 149 if err != nil { 150 return nil, err 151 } 152 153 // keep "docker run -v existing_volume:/foo --volume-driver other_driver" work 154 if (driverName != "" && v.DriverName() != driverName) || (driverName == "" && v.DriverName() != volume.DefaultDriverName) { 155 return nil, derr.ErrorVolumeNameTaken.WithArgs(name, v.DriverName()) 156 } 157 return volumeToAPIType(v), nil 158 }