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