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  }