github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/api/client/create.go (about) 1 package client 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 8 "golang.org/x/net/context" 9 10 Cli "github.com/docker/docker/cli" 11 "github.com/docker/docker/pkg/jsonmessage" 12 "github.com/docker/docker/reference" 13 "github.com/docker/docker/registry" 14 runconfigopts "github.com/docker/docker/runconfig/opts" 15 "github.com/docker/engine-api/client" 16 "github.com/docker/engine-api/types" 17 "github.com/docker/engine-api/types/container" 18 networktypes "github.com/docker/engine-api/types/network" 19 ) 20 21 func (cli *DockerCli) pullImage(image string) error { 22 return cli.pullImageCustomOut(image, cli.out) 23 } 24 25 func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error { 26 ref, err := reference.ParseNamed(image) 27 if err != nil { 28 return err 29 } 30 31 var tag string 32 switch x := reference.WithDefaultTag(ref).(type) { 33 case reference.Canonical: 34 tag = x.Digest().String() 35 case reference.NamedTagged: 36 tag = x.Tag() 37 } 38 39 // Resolve the Repository name from fqn to RepositoryInfo 40 repoInfo, err := registry.ParseRepositoryInfo(ref) 41 if err != nil { 42 return err 43 } 44 45 authConfig := cli.resolveAuthConfig(repoInfo.Index) 46 encodedAuth, err := encodeAuthToBase64(authConfig) 47 if err != nil { 48 return err 49 } 50 51 options := types.ImageCreateOptions{ 52 Parent: ref.Name(), 53 Tag: tag, 54 RegistryAuth: encodedAuth, 55 } 56 57 responseBody, err := cli.client.ImageCreate(context.Background(), options) 58 if err != nil { 59 return err 60 } 61 defer responseBody.Close() 62 63 return jsonmessage.DisplayJSONMessagesStream(responseBody, out, cli.outFd, cli.isTerminalOut, nil) 64 } 65 66 type cidFile struct { 67 path string 68 file *os.File 69 written bool 70 } 71 72 func newCIDFile(path string) (*cidFile, error) { 73 if _, err := os.Stat(path); err == nil { 74 return nil, fmt.Errorf("Container ID file found, make sure the other container isn't running or delete %s", path) 75 } 76 77 f, err := os.Create(path) 78 if err != nil { 79 return nil, fmt.Errorf("Failed to create the container ID file: %s", err) 80 } 81 82 return &cidFile{path: path, file: f}, nil 83 } 84 85 func (cli *DockerCli) createContainer(config *container.Config, hostConfig *container.HostConfig, networkingConfig *networktypes.NetworkingConfig, cidfile, name string) (*types.ContainerCreateResponse, error) { 86 var containerIDFile *cidFile 87 if cidfile != "" { 88 var err error 89 if containerIDFile, err = newCIDFile(cidfile); err != nil { 90 return nil, err 91 } 92 defer containerIDFile.Close() 93 } 94 95 ref, err := reference.ParseNamed(config.Image) 96 if err != nil { 97 return nil, err 98 } 99 ref = reference.WithDefaultTag(ref) 100 101 var trustedRef reference.Canonical 102 103 if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() { 104 var err error 105 trustedRef, err = cli.trustedReference(ref) 106 if err != nil { 107 return nil, err 108 } 109 config.Image = trustedRef.String() 110 } 111 112 //create the container 113 response, err := cli.client.ContainerCreate(config, hostConfig, networkingConfig, name) 114 115 //if image not found try to pull it 116 if err != nil { 117 if client.IsErrImageNotFound(err) { 118 fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", ref.String()) 119 120 // we don't want to write to stdout anything apart from container.ID 121 if err = cli.pullImageCustomOut(config.Image, cli.err); err != nil { 122 return nil, err 123 } 124 if ref, ok := ref.(reference.NamedTagged); ok && trustedRef != nil { 125 if err := cli.tagTrusted(trustedRef, ref); err != nil { 126 return nil, err 127 } 128 } 129 // Retry 130 var retryErr error 131 response, retryErr = cli.client.ContainerCreate(config, hostConfig, networkingConfig, name) 132 if retryErr != nil { 133 return nil, retryErr 134 } 135 } else { 136 return nil, err 137 } 138 } 139 140 for _, warning := range response.Warnings { 141 fmt.Fprintf(cli.err, "WARNING: %s\n", warning) 142 } 143 if containerIDFile != nil { 144 if err = containerIDFile.Write(response.ID); err != nil { 145 return nil, err 146 } 147 } 148 return &response, nil 149 } 150 151 // CmdCreate creates a new container from a given image. 152 // 153 // Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...] 154 func (cli *DockerCli) CmdCreate(args ...string) error { 155 cmd := Cli.Subcmd("create", []string{"IMAGE [COMMAND] [ARG...]"}, Cli.DockerCommands["create"].Description, true) 156 addTrustedFlags(cmd, true) 157 158 // These are flags not stored in Config/HostConfig 159 var ( 160 flName = cmd.String([]string{"-name"}, "", "Assign a name to the container") 161 ) 162 163 config, hostConfig, networkingConfig, cmd, err := runconfigopts.Parse(cmd, args) 164 165 if err != nil { 166 cmd.ReportError(err.Error(), true) 167 os.Exit(1) 168 } 169 if config.Image == "" { 170 cmd.Usage() 171 return nil 172 } 173 response, err := cli.createContainer(config, hostConfig, networkingConfig, hostConfig.ContainerIDFile, *flName) 174 if err != nil { 175 return err 176 } 177 fmt.Fprintf(cli.out, "%s\n", response.ID) 178 return nil 179 }