github.com/hamo/docker@v1.11.1/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  }