github.com/boynux/docker@v1.11.0-rc4/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 var trustedRef reference.Canonical 96 _, ref, err := reference.ParseIDOrReference(config.Image) 97 if err != nil { 98 return nil, err 99 } 100 if ref != nil { 101 ref = reference.WithDefaultTag(ref) 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 113 //create the container 114 response, err := cli.client.ContainerCreate(context.Background(), config, hostConfig, networkingConfig, name) 115 116 //if image not found try to pull it 117 if err != nil { 118 if client.IsErrImageNotFound(err) && ref != nil { 119 fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", ref.String()) 120 121 // we don't want to write to stdout anything apart from container.ID 122 if err = cli.pullImageCustomOut(config.Image, cli.err); err != nil { 123 return nil, err 124 } 125 if ref, ok := ref.(reference.NamedTagged); ok && trustedRef != nil { 126 if err := cli.tagTrusted(trustedRef, ref); err != nil { 127 return nil, err 128 } 129 } 130 // Retry 131 var retryErr error 132 response, retryErr = cli.client.ContainerCreate(context.Background(), config, hostConfig, networkingConfig, name) 133 if retryErr != nil { 134 return nil, retryErr 135 } 136 } else { 137 return nil, err 138 } 139 } 140 141 for _, warning := range response.Warnings { 142 fmt.Fprintf(cli.err, "WARNING: %s\n", warning) 143 } 144 if containerIDFile != nil { 145 if err = containerIDFile.Write(response.ID); err != nil { 146 return nil, err 147 } 148 } 149 return &response, nil 150 } 151 152 // CmdCreate creates a new container from a given image. 153 // 154 // Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...] 155 func (cli *DockerCli) CmdCreate(args ...string) error { 156 cmd := Cli.Subcmd("create", []string{"IMAGE [COMMAND] [ARG...]"}, Cli.DockerCommands["create"].Description, true) 157 addTrustedFlags(cmd, true) 158 159 // These are flags not stored in Config/HostConfig 160 var ( 161 flName = cmd.String([]string{"-name"}, "", "Assign a name to the container") 162 ) 163 164 config, hostConfig, networkingConfig, cmd, err := runconfigopts.Parse(cmd, args) 165 166 if err != nil { 167 cmd.ReportError(err.Error(), true) 168 os.Exit(1) 169 } 170 if config.Image == "" { 171 cmd.Usage() 172 return nil 173 } 174 response, err := cli.createContainer(config, hostConfig, networkingConfig, hostConfig.ContainerIDFile, *flName) 175 if err != nil { 176 return err 177 } 178 fmt.Fprintf(cli.out, "%s\n", response.ID) 179 return nil 180 }