package main import ( "fmt" "os" "path/filepath" "github.com/Sirupsen/logrus" "github.com/docker/docker/api/client" "github.com/docker/docker/cli" "github.com/docker/docker/cli/cobraadaptor" cliflags "github.com/docker/docker/cli/flags" "github.com/docker/docker/cliconfig" "github.com/docker/docker/dockerversion" flag "github.com/docker/docker/pkg/mflag" "github.com/docker/docker/pkg/term" "github.com/docker/docker/utils" ) var ( commonFlags = cliflags.InitCommonFlags() clientFlags = initClientFlags(commonFlags) flHelp = flag.Bool([]string{"h", "-help"}, false, "Print usage") flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit") ) func main() { // Set terminal emulation based on platform as required. stdin, stdout, stderr := term.StdStreams() logrus.SetOutput(stderr) flag.Merge(flag.CommandLine, clientFlags.FlagSet, commonFlags.FlagSet) cobraAdaptor := cobraadaptor.NewCobraAdaptor(clientFlags) flag.Usage = func() { fmt.Fprint(stdout, "Usage: docker [OPTIONS] COMMAND [arg...]\n docker [ --help | -v | --version ]\n\n") fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n") flag.CommandLine.SetOutput(stdout) flag.PrintDefaults() help := "\nCommands:\n" dockerCommands := append(cli.DockerCommandUsage, cobraAdaptor.Usage()...) for _, cmd := range sortCommands(dockerCommands) { help += fmt.Sprintf(" %-10.10s%s\n", cmd.Name, cmd.Description) } help += "\nRun 'docker COMMAND --help' for more information on a command." fmt.Fprintf(stdout, "%s\n", help) } flag.Parse() if *flVersion { showVersion() return } if *flHelp { // if global flag --help is present, regardless of what other options and commands there are, // just print the usage. flag.Usage() return } clientCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags) c := cli.New(clientCli, NewDaemonProxy(), cobraAdaptor) if err := c.Run(flag.Args()...); err != nil { if sterr, ok := err.(cli.StatusError); ok { if sterr.Status != "" { fmt.Fprintln(stderr, sterr.Status) } // StatusError should only be used for errors, and all errors should // have a non-zero exit status, so never exit with 0 if sterr.StatusCode == 0 { os.Exit(1) } os.Exit(sterr.StatusCode) } fmt.Fprintln(stderr, err) os.Exit(1) } } func showVersion() { if utils.ExperimentalBuild() { fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.Version, dockerversion.GitCommit) } else { fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit) } } func initClientFlags(commonFlags *cliflags.CommonFlags) *cliflags.ClientFlags { clientFlags := &cliflags.ClientFlags{FlagSet: new(flag.FlagSet), Common: commonFlags} client := clientFlags.FlagSet client.StringVar(&clientFlags.ConfigDir, []string{"-config"}, cliconfig.ConfigDir(), "Location of client config files") clientFlags.PostParse = func() { clientFlags.Common.PostParse() if clientFlags.ConfigDir != "" { cliconfig.SetConfigDir(clientFlags.ConfigDir) } if clientFlags.Common.TrustKey == "" { clientFlags.Common.TrustKey = filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile) } if clientFlags.Common.Debug { utils.EnableDebug() } } return clientFlags }