Browse code

Merge pull request #6052 from rhatdan/help

--help option and help command should print to stdout not stderr

Victor Vieux authored on 2014/08/28 03:17:16
Showing 38 changed files
... ...
@@ -52,8 +52,8 @@ func (cli *DockerCli) Cmd(args ...string) error {
52 52
 	if len(args) > 0 {
53 53
 		method, exists := cli.getMethod(args[0])
54 54
 		if !exists {
55
-			fmt.Println("Error: Command not found:", args[0])
56
-			return cli.CmdHelp(args[1:]...)
55
+			fmt.Fprintf(cli.err, "docker: '%s' is not a docker command. See 'docker --help'.\n", args[0])
56
+			os.Exit(1)
57 57
 		}
58 58
 		return method(args[1:]...)
59 59
 	}
... ...
@@ -63,9 +63,10 @@ func (cli *DockerCli) Cmd(args ...string) error {
63 63
 func (cli *DockerCli) Subcmd(name, signature, description string) *flag.FlagSet {
64 64
 	flags := flag.NewFlagSet(name, flag.ContinueOnError)
65 65
 	flags.Usage = func() {
66
-		fmt.Fprintf(cli.err, "\nUsage: docker %s %s\n\n%s\n\n", name, signature, description)
66
+		fmt.Fprintf(cli.out, "\nUsage: docker %s %s\n\n%s\n\n", name, signature, description)
67
+		flags.SetOutput(cli.out)
67 68
 		flags.PrintDefaults()
68
-		os.Exit(2)
69
+		os.Exit(0)
69 70
 	}
70 71
 	return flags
71 72
 }
... ...
@@ -48,6 +48,8 @@ func (cli *DockerCli) CmdHelp(args ...string) error {
48 48
 		method, exists := cli.getMethod(args[0])
49 49
 		if !exists {
50 50
 			fmt.Fprintf(cli.err, "Error: Command not found: %s\n", args[0])
51
+			fmt.Fprintf(cli.err, "docker: '%s' is not a docker command. See 'docker --help'.\n", args[0])
52
+			os.Exit(1)
51 53
 		} else {
52 54
 			method("--help")
53 55
 			return nil
... ...
@@ -93,7 +95,7 @@ func (cli *DockerCli) CmdHelp(args ...string) error {
93 93
 	} {
94 94
 		help += fmt.Sprintf("    %-10.10s%s\n", command[0], command[1])
95 95
 	}
96
-	fmt.Fprintf(cli.err, "%s\n", help)
96
+	fmt.Fprintf(cli.out, "%s\n", help)
97 97
 	return nil
98 98
 }
99 99
 
... ...
@@ -104,13 +106,18 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
104 104
 	noCache := cmd.Bool([]string{"#no-cache", "-no-cache"}, false, "Do not use cache when building the image")
105 105
 	rm := cmd.Bool([]string{"#rm", "-rm"}, true, "Remove intermediate containers after a successful build")
106 106
 	forceRm := cmd.Bool([]string{"-force-rm"}, false, "Always remove intermediate containers, even after unsuccessful builds")
107
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
108
+
107 109
 	if err := cmd.Parse(args); err != nil {
108 110
 		return nil
109 111
 	}
110
-	if cmd.NArg() != 1 {
112
+	if *help {
111 113
 		cmd.Usage()
112 114
 		return nil
113 115
 	}
116
+	if cmd.BadArgs(1) {
117
+		os.Exit(1)
118
+	}
114 119
 
115 120
 	var (
116 121
 		context  archive.Archive
... ...
@@ -262,10 +269,16 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
262 262
 	cmd.StringVar(&username, []string{"u", "-username"}, "", "Username")
263 263
 	cmd.StringVar(&password, []string{"p", "-password"}, "", "Password")
264 264
 	cmd.StringVar(&email, []string{"e", "-email"}, "", "Email")
265
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
266
+
265 267
 	err := cmd.Parse(args)
266 268
 	if err != nil {
267 269
 		return nil
268 270
 	}
271
+	if *help {
272
+		cmd.Usage()
273
+		return nil
274
+	}
269 275
 	serverAddress := registry.IndexServerAddress()
270 276
 	if len(cmd.Args()) > 0 {
271 277
 		serverAddress = cmd.Arg(0)
... ...
@@ -385,13 +398,18 @@ func (cli *DockerCli) CmdLogout(args ...string) error {
385 385
 // 'docker wait': block until a container stops
386 386
 func (cli *DockerCli) CmdWait(args ...string) error {
387 387
 	cmd := cli.Subcmd("wait", "CONTAINER [CONTAINER...]", "Block until a container stops, then print its exit code.")
388
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
389
+
388 390
 	if err := cmd.Parse(args); err != nil {
389 391
 		return nil
390 392
 	}
391
-	if cmd.NArg() < 1 {
393
+	if *help {
392 394
 		cmd.Usage()
393 395
 		return nil
394 396
 	}
397
+	if cmd.BadArgs(1) {
398
+		os.Exit(1)
399
+	}
395 400
 	var encounteredError error
396 401
 	for _, name := range cmd.Args() {
397 402
 		status, err := waitForExit(cli, name)
... ...
@@ -411,10 +429,8 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
411 411
 	if err := cmd.Parse(args); err != nil {
412 412
 		return nil
413 413
 	}
414
-
415
-	if cmd.NArg() > 0 {
416
-		cmd.Usage()
417
-		return nil
414
+	if cmd.BadArgs(0) {
415
+		os.Exit(1)
418 416
 	}
419 417
 	if dockerversion.VERSION != "" {
420 418
 		fmt.Fprintf(cli.out, "Client version: %s\n", dockerversion.VERSION)
... ...
@@ -457,9 +473,8 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
457 457
 	if err := cmd.Parse(args); err != nil {
458 458
 		return nil
459 459
 	}
460
-	if cmd.NArg() > 0 {
461
-		cmd.Usage()
462
-		return nil
460
+	if cmd.BadArgs(0) {
461
+		os.Exit(1)
463 462
 	}
464 463
 
465 464
 	body, _, err := readBody(cli.call("GET", "/info", nil, false))
... ...
@@ -531,13 +546,18 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
531 531
 func (cli *DockerCli) CmdStop(args ...string) error {
532 532
 	cmd := cli.Subcmd("stop", "[OPTIONS] CONTAINER [CONTAINER...]", "Stop a running container by sending SIGTERM and then SIGKILL after a grace period")
533 533
 	nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Number of seconds to wait for the container to stop before killing it. Default is 10 seconds.")
534
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
535
+
534 536
 	if err := cmd.Parse(args); err != nil {
535 537
 		return nil
536 538
 	}
537
-	if cmd.NArg() < 1 {
539
+	if *help {
538 540
 		cmd.Usage()
539 541
 		return nil
540 542
 	}
543
+	if cmd.BadArgs(1) {
544
+		os.Exit(1)
545
+	}
541 546
 
542 547
 	v := url.Values{}
543 548
 	v.Set("t", strconv.Itoa(*nSeconds))
... ...
@@ -558,13 +578,18 @@ func (cli *DockerCli) CmdStop(args ...string) error {
558 558
 func (cli *DockerCli) CmdRestart(args ...string) error {
559 559
 	cmd := cli.Subcmd("restart", "[OPTIONS] CONTAINER [CONTAINER...]", "Restart a running container")
560 560
 	nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Number of seconds to try to stop for before killing the container. Once killed it will then be restarted. Default is 10 seconds.")
561
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
562
+
561 563
 	if err := cmd.Parse(args); err != nil {
562 564
 		return nil
563 565
 	}
564
-	if cmd.NArg() < 1 {
566
+	if *help {
565 567
 		cmd.Usage()
566 568
 		return nil
567 569
 	}
570
+	if cmd.BadArgs(1) {
571
+		os.Exit(1)
572
+	}
568 573
 
569 574
 	v := url.Values{}
570 575
 	v.Set("t", strconv.Itoa(*nSeconds))
... ...
@@ -616,15 +641,19 @@ func (cli *DockerCli) CmdStart(args ...string) error {
616 616
 		cmd       = cli.Subcmd("start", "CONTAINER [CONTAINER...]", "Restart a stopped container")
617 617
 		attach    = cmd.Bool([]string{"a", "-attach"}, false, "Attach container's STDOUT and STDERR and forward all signals to the process")
618 618
 		openStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Attach container's STDIN")
619
+		help      = cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
619 620
 	)
620 621
 
621 622
 	if err := cmd.Parse(args); err != nil {
622 623
 		return nil
623 624
 	}
624
-	if cmd.NArg() < 1 {
625
+	if *help {
625 626
 		cmd.Usage()
626 627
 		return nil
627 628
 	}
629
+	if cmd.BadArgs(1) {
630
+		os.Exit(1)
631
+	}
628 632
 
629 633
 	if *attach || *openStdin {
630 634
 		if cmd.NArg() > 1 {
... ...
@@ -704,10 +733,8 @@ func (cli *DockerCli) CmdUnpause(args ...string) error {
704 704
 	if err := cmd.Parse(args); err != nil {
705 705
 		return nil
706 706
 	}
707
-
708
-	if cmd.NArg() != 1 {
709
-		cmd.Usage()
710
-		return nil
707
+	if cmd.BadArgs(1) {
708
+		os.Exit(1)
711 709
 	}
712 710
 
713 711
 	var encounteredError error
... ...
@@ -727,10 +754,8 @@ func (cli *DockerCli) CmdPause(args ...string) error {
727 727
 	if err := cmd.Parse(args); err != nil {
728 728
 		return nil
729 729
 	}
730
-
731
-	if cmd.NArg() != 1 {
732
-		cmd.Usage()
733
-		return nil
730
+	if cmd.BadArgs(1) {
731
+		os.Exit(1)
734 732
 	}
735 733
 
736 734
 	var encounteredError error
... ...
@@ -748,13 +773,18 @@ func (cli *DockerCli) CmdPause(args ...string) error {
748 748
 func (cli *DockerCli) CmdInspect(args ...string) error {
749 749
 	cmd := cli.Subcmd("inspect", "CONTAINER|IMAGE [CONTAINER|IMAGE...]", "Return low-level information on a container or image")
750 750
 	tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template.")
751
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
752
+
751 753
 	if err := cmd.Parse(args); err != nil {
752 754
 		return nil
753 755
 	}
754
-	if cmd.NArg() < 1 {
756
+	if *help {
755 757
 		cmd.Usage()
756 758
 		return nil
757 759
 	}
760
+	if cmd.BadArgs(1) {
761
+		os.Exit(1)
762
+	}
758 763
 
759 764
 	var tmpl *template.Template
760 765
 	if *tmplStr != "" {
... ...
@@ -827,13 +857,18 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
827 827
 
828 828
 func (cli *DockerCli) CmdTop(args ...string) error {
829 829
 	cmd := cli.Subcmd("top", "CONTAINER [ps OPTIONS]", "Display the running processes of a container")
830
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
831
+
830 832
 	if err := cmd.Parse(args); err != nil {
831 833
 		return nil
832 834
 	}
833
-	if cmd.NArg() == 0 {
835
+	if *help {
834 836
 		cmd.Usage()
835 837
 		return nil
836 838
 	}
839
+	if cmd.BadArgs(1) {
840
+		os.Exit(1)
841
+	}
837 842
 	val := url.Values{}
838 843
 	if cmd.NArg() > 1 {
839 844
 		val.Set("ps_args", strings.Join(cmd.Args()[1:], " "))
... ...
@@ -862,13 +897,17 @@ func (cli *DockerCli) CmdTop(args ...string) error {
862 862
 
863 863
 func (cli *DockerCli) CmdPort(args ...string) error {
864 864
 	cmd := cli.Subcmd("port", "CONTAINER PRIVATE_PORT", "Lookup the public-facing port that is NAT-ed to PRIVATE_PORT")
865
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
865 866
 	if err := cmd.Parse(args); err != nil {
866 867
 		return nil
867 868
 	}
868
-	if cmd.NArg() != 2 {
869
+	if *help {
869 870
 		cmd.Usage()
870 871
 		return nil
871 872
 	}
873
+	if cmd.BadArgs(2) {
874
+		os.Exit(1)
875
+	}
872 876
 
873 877
 	var (
874 878
 		port  = cmd.Arg(1)
... ...
@@ -912,13 +951,18 @@ func (cli *DockerCli) CmdRmi(args ...string) error {
912 912
 		force   = cmd.Bool([]string{"f", "-force"}, false, "Force removal of the image")
913 913
 		noprune = cmd.Bool([]string{"-no-prune"}, false, "Do not delete untagged parents")
914 914
 	)
915
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
916
+
915 917
 	if err := cmd.Parse(args); err != nil {
916 918
 		return nil
917 919
 	}
918
-	if cmd.NArg() < 1 {
920
+	if *help {
919 921
 		cmd.Usage()
920 922
 		return nil
921 923
 	}
924
+	if cmd.BadArgs(1) {
925
+		os.Exit(1)
926
+	}
922 927
 
923 928
 	v := url.Values{}
924 929
 	if *force {
... ...
@@ -957,14 +1001,18 @@ func (cli *DockerCli) CmdHistory(args ...string) error {
957 957
 	cmd := cli.Subcmd("history", "[OPTIONS] IMAGE", "Show the history of an image")
958 958
 	quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs")
959 959
 	noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
960
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
960 961
 
961 962
 	if err := cmd.Parse(args); err != nil {
962 963
 		return nil
963 964
 	}
964
-	if cmd.NArg() != 1 {
965
+	if *help {
965 966
 		cmd.Usage()
966 967
 		return nil
967 968
 	}
969
+	if cmd.BadArgs(1) {
970
+		os.Exit(1)
971
+	}
968 972
 
969 973
 	body, _, err := readBody(cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, false))
970 974
 	if err != nil {
... ...
@@ -1015,14 +1063,18 @@ func (cli *DockerCli) CmdRm(args ...string) error {
1015 1015
 	v := cmd.Bool([]string{"v", "-volumes"}, false, "Remove the volumes associated with the container")
1016 1016
 	link := cmd.Bool([]string{"l", "#link", "-link"}, false, "Remove the specified link and not the underlying container")
1017 1017
 	force := cmd.Bool([]string{"f", "-force"}, false, "Force the removal of a running container (uses SIGKILL)")
1018
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1018 1019
 
1019 1020
 	if err := cmd.Parse(args); err != nil {
1020 1021
 		return nil
1021 1022
 	}
1022
-	if cmd.NArg() < 1 {
1023
+	if *help {
1023 1024
 		cmd.Usage()
1024 1025
 		return nil
1025 1026
 	}
1027
+	if cmd.BadArgs(1) {
1028
+		os.Exit(1)
1029
+	}
1026 1030
 
1027 1031
 	val := url.Values{}
1028 1032
 	if *v {
... ...
@@ -1053,14 +1105,18 @@ func (cli *DockerCli) CmdRm(args ...string) error {
1053 1053
 func (cli *DockerCli) CmdKill(args ...string) error {
1054 1054
 	cmd := cli.Subcmd("kill", "[OPTIONS] CONTAINER [CONTAINER...]", "Kill a running container using SIGKILL or a specified signal")
1055 1055
 	signal := cmd.String([]string{"s", "-signal"}, "KILL", "Signal to send to the container")
1056
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1056 1057
 
1057 1058
 	if err := cmd.Parse(args); err != nil {
1058 1059
 		return nil
1059 1060
 	}
1060
-	if cmd.NArg() < 1 {
1061
+	if *help {
1061 1062
 		cmd.Usage()
1062 1063
 		return nil
1063 1064
 	}
1065
+	if cmd.BadArgs(1) {
1066
+		os.Exit(1)
1067
+	}
1064 1068
 
1065 1069
 	var encounteredError error
1066 1070
 	for _, name := range cmd.Args() {
... ...
@@ -1076,15 +1132,18 @@ func (cli *DockerCli) CmdKill(args ...string) error {
1076 1076
 
1077 1077
 func (cli *DockerCli) CmdImport(args ...string) error {
1078 1078
 	cmd := cli.Subcmd("import", "URL|- [REPOSITORY[:TAG]]", "Create an empty filesystem image and import the contents of the tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) into it, then optionally tag it.")
1079
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1079 1080
 
1080 1081
 	if err := cmd.Parse(args); err != nil {
1081 1082
 		return nil
1082 1083
 	}
1083
-	if cmd.NArg() < 1 {
1084
+	if *help {
1084 1085
 		cmd.Usage()
1085 1086
 		return nil
1086 1087
 	}
1087
-
1088
+	if cmd.BadArgs(2) {
1089
+		os.Exit(1)
1090
+	}
1088 1091
 	var (
1089 1092
 		v          = url.Values{}
1090 1093
 		src        = cmd.Arg(0)
... ...
@@ -1118,9 +1177,15 @@ func (cli *DockerCli) CmdImport(args ...string) error {
1118 1118
 
1119 1119
 func (cli *DockerCli) CmdPush(args ...string) error {
1120 1120
 	cmd := cli.Subcmd("push", "NAME[:TAG]", "Push an image or a repository to the registry")
1121
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1122
+
1121 1123
 	if err := cmd.Parse(args); err != nil {
1122 1124
 		return nil
1123 1125
 	}
1126
+	if *help {
1127
+		cmd.Usage()
1128
+		return nil
1129
+	}
1124 1130
 	name := cmd.Arg(0)
1125 1131
 
1126 1132
 	if name == "" {
... ...
@@ -1184,14 +1249,19 @@ func (cli *DockerCli) CmdPush(args ...string) error {
1184 1184
 func (cli *DockerCli) CmdPull(args ...string) error {
1185 1185
 	cmd := cli.Subcmd("pull", "NAME[:TAG]", "Pull an image or a repository from the registry")
1186 1186
 	tag := cmd.String([]string{"#t", "#-tag"}, "", "Download tagged image in a repository")
1187
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1188
+
1187 1189
 	if err := cmd.Parse(args); err != nil {
1188 1190
 		return nil
1189 1191
 	}
1190
-
1191
-	if cmd.NArg() != 1 {
1192
+	if *help {
1192 1193
 		cmd.Usage()
1193 1194
 		return nil
1194 1195
 	}
1196
+
1197
+	if cmd.BadArgs(1) {
1198
+		os.Exit(1)
1199
+	}
1195 1200
 	var (
1196 1201
 		v      = url.Values{}
1197 1202
 		remote = cmd.Arg(0)
... ...
@@ -1252,6 +1322,7 @@ func (cli *DockerCli) CmdImages(args ...string) error {
1252 1252
 	// FIXME: --viz and --tree are deprecated. Remove them in a future version.
1253 1253
 	flViz := cmd.Bool([]string{"#v", "#viz", "#-viz"}, false, "Output graph in graphviz format")
1254 1254
 	flTree := cmd.Bool([]string{"#t", "#tree", "#-tree"}, false, "Output graph in tree format")
1255
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1255 1256
 
1256 1257
 	flFilter := opts.NewListOpts(nil)
1257 1258
 	cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values (i.e. 'dangling=true')")
... ...
@@ -1259,10 +1330,13 @@ func (cli *DockerCli) CmdImages(args ...string) error {
1259 1259
 	if err := cmd.Parse(args); err != nil {
1260 1260
 		return nil
1261 1261
 	}
1262
-	if cmd.NArg() > 1 {
1262
+	if *help {
1263 1263
 		cmd.Usage()
1264 1264
 		return nil
1265 1265
 	}
1266
+	if cmd.BadArgs(1) {
1267
+		os.Exit(1)
1268
+	}
1266 1269
 
1267 1270
 	// Consolidate all filter flags, and sanity check them early.
1268 1271
 	// They'll get process in the daemon/server.
... ...
@@ -1485,6 +1559,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
1485 1485
 	since := cmd.String([]string{"#sinceId", "#-since-id", "-since"}, "", "Show only containers created since Id or Name, include non-running ones.")
1486 1486
 	before := cmd.String([]string{"#beforeId", "#-before-id", "-before"}, "", "Show only container created before Id or Name, include non-running ones.")
1487 1487
 	last := cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running ones.")
1488
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1488 1489
 
1489 1490
 	flFilter := opts.NewListOpts(nil)
1490 1491
 	cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values. Valid filters:\nexited=<int> - containers with exit code of <int>")
... ...
@@ -1492,6 +1567,10 @@ func (cli *DockerCli) CmdPs(args ...string) error {
1492 1492
 	if err := cmd.Parse(args); err != nil {
1493 1493
 		return nil
1494 1494
 	}
1495
+	if *help {
1496
+		cmd.Usage()
1497
+		return nil
1498
+	}
1495 1499
 	v := url.Values{}
1496 1500
 	if *last == -1 && *nLatest {
1497 1501
 		*last = 1
... ...
@@ -1602,9 +1681,14 @@ func (cli *DockerCli) CmdCommit(args ...string) error {
1602 1602
 	flAuthor := cmd.String([]string{"a", "#author", "-author"}, "", "Author (e.g., \"John Hannibal Smith <hannibal@a-team.com>\")")
1603 1603
 	// FIXME: --run is deprecated, it will be replaced with inline Dockerfile commands.
1604 1604
 	flConfig := cmd.String([]string{"#run", "#-run"}, "", "This option is deprecated and will be removed in a future version in favor of inline Dockerfile-compatible commands")
1605
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1605 1606
 	if err := cmd.Parse(args); err != nil {
1606 1607
 		return nil
1607 1608
 	}
1609
+	if *help {
1610
+		cmd.Usage()
1611
+		return nil
1612
+	}
1608 1613
 
1609 1614
 	var (
1610 1615
 		name            = cmd.Arg(0)
... ...
@@ -1660,14 +1744,19 @@ func (cli *DockerCli) CmdEvents(args ...string) error {
1660 1660
 	cmd := cli.Subcmd("events", "[OPTIONS]", "Get real time events from the server")
1661 1661
 	since := cmd.String([]string{"#since", "-since"}, "", "Show all events created since timestamp")
1662 1662
 	until := cmd.String([]string{"-until"}, "", "Stream events until this timestamp")
1663
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1664
+
1663 1665
 	if err := cmd.Parse(args); err != nil {
1664 1666
 		return nil
1665 1667
 	}
1666
-
1667
-	if cmd.NArg() != 0 {
1668
+	if *help {
1668 1669
 		cmd.Usage()
1669 1670
 		return nil
1670 1671
 	}
1672
+	if cmd.BadArgs(0) {
1673
+		os.Exit(1)
1674
+	}
1675
+
1671 1676
 	var (
1672 1677
 		v   = url.Values{}
1673 1678
 		loc = time.FixedZone(time.Now().Zone())
... ...
@@ -1697,14 +1786,18 @@ func (cli *DockerCli) CmdEvents(args ...string) error {
1697 1697
 
1698 1698
 func (cli *DockerCli) CmdExport(args ...string) error {
1699 1699
 	cmd := cli.Subcmd("export", "CONTAINER", "Export the contents of a filesystem as a tar archive to STDOUT")
1700
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1701
+
1700 1702
 	if err := cmd.Parse(args); err != nil {
1701 1703
 		return nil
1702 1704
 	}
1703
-
1704
-	if cmd.NArg() != 1 {
1705
+	if *help {
1705 1706
 		cmd.Usage()
1706 1707
 		return nil
1707 1708
 	}
1709
+	if cmd.BadArgs(1) {
1710
+		os.Exit(1)
1711
+	}
1708 1712
 
1709 1713
 	if err := cli.stream("GET", "/containers/"+cmd.Arg(0)+"/export", nil, cli.out, nil); err != nil {
1710 1714
 		return err
... ...
@@ -1714,13 +1807,18 @@ func (cli *DockerCli) CmdExport(args ...string) error {
1714 1714
 
1715 1715
 func (cli *DockerCli) CmdDiff(args ...string) error {
1716 1716
 	cmd := cli.Subcmd("diff", "CONTAINER", "Inspect changes on a container's filesystem")
1717
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1718
+
1717 1719
 	if err := cmd.Parse(args); err != nil {
1718 1720
 		return nil
1719 1721
 	}
1720
-	if cmd.NArg() != 1 {
1722
+	if *help {
1721 1723
 		cmd.Usage()
1722 1724
 		return nil
1723 1725
 	}
1726
+	if cmd.BadArgs(1) {
1727
+		os.Exit(1)
1728
+	}
1724 1729
 
1725 1730
 	body, _, err := readBody(cli.call("GET", "/containers/"+cmd.Arg(0)+"/changes", nil, false))
1726 1731
 
... ...
@@ -1753,16 +1851,19 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
1753 1753
 		follow = cmd.Bool([]string{"f", "-follow"}, false, "Follow log output")
1754 1754
 		times  = cmd.Bool([]string{"t", "-timestamps"}, false, "Show timestamps")
1755 1755
 		tail   = cmd.String([]string{"-tail"}, "all", "Output the specified number of lines at the end of logs (defaults to all logs)")
1756
+		help   = cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1756 1757
 	)
1757 1758
 
1758 1759
 	if err := cmd.Parse(args); err != nil {
1759 1760
 		return nil
1760 1761
 	}
1761
-
1762
-	if cmd.NArg() != 1 {
1762
+	if *help {
1763 1763
 		cmd.Usage()
1764 1764
 		return nil
1765 1765
 	}
1766
+	if cmd.BadArgs(1) {
1767
+		os.Exit(1)
1768
+	}
1766 1769
 	name := cmd.Arg(0)
1767 1770
 
1768 1771
 	steam, _, err := cli.call("GET", "/containers/"+name+"/json", nil, false)
... ...
@@ -1796,16 +1897,19 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
1796 1796
 		cmd     = cli.Subcmd("attach", "[OPTIONS] CONTAINER", "Attach to a running container")
1797 1797
 		noStdin = cmd.Bool([]string{"#nostdin", "-no-stdin"}, false, "Do not attach STDIN")
1798 1798
 		proxy   = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxy all received signals to the process (even in non-TTY mode). SIGCHLD, SIGKILL, and SIGSTOP are not proxied.")
1799
+		help    = cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1799 1800
 	)
1800 1801
 
1801 1802
 	if err := cmd.Parse(args); err != nil {
1802 1803
 		return nil
1803 1804
 	}
1804
-
1805
-	if cmd.NArg() != 1 {
1805
+	if *help {
1806 1806
 		cmd.Usage()
1807 1807
 		return nil
1808 1808
 	}
1809
+	if cmd.BadArgs(1) {
1810
+		os.Exit(1)
1811
+	}
1809 1812
 	name := cmd.Arg(0)
1810 1813
 
1811 1814
 	stream, _, err := cli.call("GET", "/containers/"+name+"/json", nil, false)
... ...
@@ -1871,13 +1975,18 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
1871 1871
 	trusted := cmd.Bool([]string{"#t", "#trusted", "#-trusted"}, false, "Only show trusted builds")
1872 1872
 	automated := cmd.Bool([]string{"-automated"}, false, "Only show automated builds")
1873 1873
 	stars := cmd.Int([]string{"s", "#stars", "-stars"}, 0, "Only displays with at least x stars")
1874
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1875
+
1874 1876
 	if err := cmd.Parse(args); err != nil {
1875 1877
 		return nil
1876 1878
 	}
1877
-	if cmd.NArg() != 1 {
1879
+	if *help {
1878 1880
 		cmd.Usage()
1879 1881
 		return nil
1880 1882
 	}
1883
+	if cmd.BadArgs(1) {
1884
+		os.Exit(1)
1885
+	}
1881 1886
 
1882 1887
 	v := url.Values{}
1883 1888
 	v.Set("term", cmd.Arg(0))
... ...
@@ -1923,13 +2032,18 @@ type ports []int
1923 1923
 func (cli *DockerCli) CmdTag(args ...string) error {
1924 1924
 	cmd := cli.Subcmd("tag", "[OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]", "Tag an image into a repository")
1925 1925
 	force := cmd.Bool([]string{"f", "#force", "-force"}, false, "Force")
1926
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
1927
+
1926 1928
 	if err := cmd.Parse(args); err != nil {
1927 1929
 		return nil
1928 1930
 	}
1929
-	if cmd.NArg() != 2 {
1931
+	if *help {
1930 1932
 		cmd.Usage()
1931 1933
 		return nil
1932 1934
 	}
1935
+	if cmd.BadArgs(2) {
1936
+		os.Exit(1)
1937
+	}
1933 1938
 
1934 1939
 	var (
1935 1940
 		repository, tag = parsers.ParseRepositoryTag(cmd.Arg(1))
... ...
@@ -1994,6 +2108,11 @@ func (cli *DockerCli) CmdRun(args ...string) error {
1994 1994
 	if err != nil {
1995 1995
 		return err
1996 1996
 	}
1997
+	if config == nil {
1998
+		cmd.Usage()
1999
+		return nil
2000
+	}
2001
+
1997 2002
 	if config.Image == "" {
1998 2003
 		cmd.Usage()
1999 2004
 		return nil
... ...
@@ -2216,14 +2335,18 @@ func (cli *DockerCli) CmdRun(args ...string) error {
2216 2216
 
2217 2217
 func (cli *DockerCli) CmdCp(args ...string) error {
2218 2218
 	cmd := cli.Subcmd("cp", "CONTAINER:PATH HOSTPATH", "Copy files/folders from the PATH to the HOSTPATH")
2219
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
2220
+
2219 2221
 	if err := cmd.Parse(args); err != nil {
2220 2222
 		return nil
2221 2223
 	}
2222
-
2223
-	if cmd.NArg() != 2 {
2224
+	if *help {
2224 2225
 		cmd.Usage()
2225 2226
 		return nil
2226 2227
 	}
2228
+	if cmd.BadArgs(2) {
2229
+		os.Exit(1)
2230
+	}
2227 2231
 
2228 2232
 	var copyData engine.Env
2229 2233
 	info := strings.Split(cmd.Arg(0), ":")
... ...
@@ -2257,15 +2380,18 @@ func (cli *DockerCli) CmdCp(args ...string) error {
2257 2257
 func (cli *DockerCli) CmdSave(args ...string) error {
2258 2258
 	cmd := cli.Subcmd("save", "IMAGE", "Save an image to a tar archive (streamed to STDOUT by default)")
2259 2259
 	outfile := cmd.String([]string{"o", "-output"}, "", "Write to an file, instead of STDOUT")
2260
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
2260 2261
 
2261 2262
 	if err := cmd.Parse(args); err != nil {
2262 2263
 		return err
2263 2264
 	}
2264
-
2265
-	if cmd.NArg() != 1 {
2265
+	if *help {
2266 2266
 		cmd.Usage()
2267 2267
 		return nil
2268 2268
 	}
2269
+	if cmd.BadArgs(1) {
2270
+		os.Exit(1)
2271
+	}
2269 2272
 
2270 2273
 	var (
2271 2274
 		output io.Writer = cli.out
... ...
@@ -2287,15 +2413,18 @@ func (cli *DockerCli) CmdSave(args ...string) error {
2287 2287
 func (cli *DockerCli) CmdLoad(args ...string) error {
2288 2288
 	cmd := cli.Subcmd("load", "", "Load an image from a tar archive on STDIN")
2289 2289
 	infile := cmd.String([]string{"i", "-input"}, "", "Read from a tar archive file, instead of STDIN")
2290
+	help := cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
2290 2291
 
2291 2292
 	if err := cmd.Parse(args); err != nil {
2292 2293
 		return err
2293 2294
 	}
2294
-
2295
-	if cmd.NArg() != 0 {
2295
+	if *help {
2296 2296
 		cmd.Usage()
2297 2297
 		return nil
2298 2298
 	}
2299
+	if cmd.BadArgs(0) {
2300
+		os.Exit(1)
2301
+	}
2299 2302
 
2300 2303
 	var (
2301 2304
 		input io.Reader = cli.in
... ...
@@ -26,6 +26,7 @@ var (
26 26
 	flEnableCors  = flag.Bool([]string{"#api-enable-cors", "-api-enable-cors"}, false, "Enable CORS headers in the remote API")
27 27
 	flTls         = flag.Bool([]string{"-tls"}, false, "Use TLS; implied by tls-verify flags")
28 28
 	flTlsVerify   = flag.Bool([]string{"-tlsverify"}, false, "Use TLS and verify the remote (daemon: verify client, client: verify daemon)")
29
+	flHelp        = flag.Bool([]string{"h", "-help"}, false, "Print usage")
29 30
 
30 31
 	// these are initialized in init() below since their default values depend on dockerCertPath which isn't fully initialized until init() runs
31 32
 	flCa    *string
... ...
@@ -6,6 +6,7 @@ docker-attach - Attach to a running container
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker attach**
9
+[**--help**]/
9 10
 [**--no-stdin**[=*false*]]
10 11
 [**--sig-proxy**[=*true*]]
11 12
  CONTAINER
... ...
@@ -21,6 +22,9 @@ When you detach from a container the exit code will be returned to
21 21
 the client.
22 22
 
23 23
 # OPTIONS
24
+**--help**
25
+  Print usage statement
26
+
24 27
 **--no-stdin**=*true*|*false*
25 28
    Do not attach STDIN. The default is *false*.
26 29
 
... ...
@@ -6,6 +6,7 @@ docker-build - Build a new image from the source code at PATH
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker build**
9
+[**--help**]
9 10
 [**--force-rm**[=*false*]]
10 11
 [**--no-cache**[=*false*]]
11 12
 [**-q**|**--quiet**[=*false*]]
... ...
@@ -36,6 +37,9 @@ as context.
36 36
 **--no-cache**=*true*|*false*
37 37
    Do not use cache when building the image. The default is *false*.
38 38
 
39
+**--help**
40
+  Print usage statement
41
+
39 42
 **-q**, **--quiet**=*true*|*false*
40 43
    Suppress the verbose output generated by the containers. The default is *false*.
41 44
 
... ...
@@ -7,6 +7,7 @@ docker-commit - Create a new image from a container's changes
7 7
 # SYNOPSIS
8 8
 **docker commit**
9 9
 [**-a**|**--author**[=*AUTHOR*]]
10
+[**--help**]
10 11
 [**-m**|**--message**[=*MESSAGE*]]
11 12
 [**-p**|**--pause**[=*true*]]
12 13
  CONTAINER [REPOSITORY[:TAG]]
... ...
@@ -18,6 +19,9 @@ Using an existing container's name or ID you can create a new image.
18 18
 **-a**, **--author**=""
19 19
    Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
20 20
 
21
+**--help**
22
+  Print usage statement
23
+
21 24
 **-m**, **--message**=""
22 25
    Commit message
23 26
 
... ...
@@ -6,6 +6,7 @@ docker-cp - Copy files/folders from the PATH to the HOSTPATH
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker cp**
9
+[**--help**]
9 10
 CONTAINER:PATH HOSTPATH
10 11
 
11 12
 # DESCRIPTION
... ...
@@ -14,7 +15,8 @@ path. Paths are relative to the root of the filesystem. Files
14 14
 can be copied from a running or stopped container.
15 15
 
16 16
 # OPTIONS
17
-There are no available options.
17
+**--help**
18
+  Print usage statement
18 19
 
19 20
 # EXAMPLES
20 21
 An important shell script file, created in a bash shell, is copied from
... ...
@@ -6,6 +6,7 @@ docker-diff - Inspect changes on a container's filesystem
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker diff**
9
+[**--help**]
9 10
 CONTAINER
10 11
 
11 12
 # DESCRIPTION
... ...
@@ -14,7 +15,8 @@ shortened container ID or the container name set using
14 14
 **docker run --name** option.
15 15
 
16 16
 # OPTIONS
17
-There are no available options.
17
+**--help**
18
+  Print usage statement
18 19
 
19 20
 # EXAMPLES
20 21
 Inspect the changes to on a nginx container:
... ...
@@ -6,6 +6,7 @@ docker-events - Get real time events from the server
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker events**
9
+[**--help**]
9 10
 [**--since**[=*SINCE*]]
10 11
 [**--until**[=*UNTIL*]]
11 12
 
... ...
@@ -15,6 +16,9 @@ Get event information from the Docker daemon. Information can include historical
15 15
 information and real-time information.
16 16
 
17 17
 # OPTIONS
18
+**--help**
19
+  Print usage statement
20
+
18 21
 **--since**=""
19 22
    Show all events created since timestamp
20 23
 
... ...
@@ -6,6 +6,7 @@ docker-export - Export the contents of a filesystem as a tar archive to STDOUT
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker export**
9
+[**--help**]
9 10
 CONTAINER
10 11
 
11 12
 # DESCRIPTION
... ...
@@ -14,7 +15,8 @@ container ID or container name. The output is exported to STDOUT and can be
14 14
 redirected to a tar file.
15 15
 
16 16
 # OPTIONS
17
-There are no available options.
17
+**--help**
18
+  Print usage statement
18 19
 
19 20
 # EXAMPLES
20 21
 Export the contents of the container called angry_bell to a tar file
... ...
@@ -6,6 +6,7 @@ docker-history - Show the history of an image
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker history**
9
+[**--help**]
9 10
 [**--no-trunc**[=*false*]]
10 11
 [**-q**|**--quiet**[=*false*]]
11 12
  IMAGE
... ...
@@ -15,6 +16,9 @@ docker-history - Show the history of an image
15 15
 Show the history of when and how an image was created.
16 16
 
17 17
 # OPTIONS
18
+**--help**
19
+  Print usage statement
20
+
18 21
 **--no-trunc**=*true*|*false*
19 22
    Don't truncate output. The default is *false*.
20 23
 
... ...
@@ -6,6 +6,7 @@ docker-images - List images
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker images**
9
+[**--help**]
9 10
 [**-a**|**--all**[=*false*]]
10 11
 [**-f**|**--filter**[=*[]*]]
11 12
 [**--no-trunc**[=*false*]]
... ...
@@ -35,6 +36,9 @@ versions.
35 35
 **-f**, **--filter**=[]
36 36
    Provide filter values (i.e. 'dangling=true')
37 37
 
38
+**--help**
39
+  Print usage statement
40
+
38 41
 **--no-trunc**=*true*|*false*
39 42
    Don't truncate output. The default is *false*.
40 43
 
... ...
@@ -6,6 +6,7 @@ docker-import - Create an empty filesystem image and import the contents of the
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker import**
9
+[**--help**]
9 10
 URL|- [REPOSITORY[:TAG]]
10 11
 
11 12
 # DESCRIPTION
... ...
@@ -13,7 +14,8 @@ Create a new filesystem image from the contents of a tarball (`.tar`,
13 13
 `.tar.gz`, `.tgz`, `.bzip`, `.tar.xz`, `.txz`) into it, then optionally tag it.
14 14
 
15 15
 # OPTIONS
16
-There are no available options.
16
+**--help**
17
+  Print usage statement
17 18
 
18 19
 # EXAMPLES
19 20
 
... ...
@@ -6,6 +6,7 @@ docker-info - Display system-wide information
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker info**
9
+[**--help**]
9 10
 
10 11
 
11 12
 # DESCRIPTION
... ...
@@ -20,7 +21,8 @@ allocates a certain amount of data space and meta data space from the space
20 20
 available on the volume where `/var/lib/docker` is mounted.
21 21
 
22 22
 # OPTIONS
23
-There are no available options.
23
+**--help**
24
+  Print usage statement
24 25
 
25 26
 # EXAMPLES
26 27
 
... ...
@@ -6,6 +6,7 @@ docker-inspect - Return low-level information on a container or image
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker inspect**
9
+[**--help**]
9 10
 [**-f**|**--format**[=*FORMAT*]]
10 11
 CONTAINER|IMAGE [CONTAINER|IMAGE...]
11 12
 
... ...
@@ -17,6 +18,9 @@ array. If a format is specified, the given template will be executed for
17 17
 each result.
18 18
 
19 19
 # OPTIONS
20
+**--help**
21
+  Print usage statement
22
+
20 23
 **-f**, **--format**=""
21 24
    Format the output using the given go template.
22 25
 
... ...
@@ -6,6 +6,7 @@ docker-kill - Kill a running container using SIGKILL or a specified signal
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker kill**
9
+[**--help**]
9 10
 [**-s**|**--signal**[=*"KILL"*]]
10 11
  CONTAINER [CONTAINER...]
11 12
 
... ...
@@ -15,6 +16,9 @@ The main process inside each container specified will be sent SIGKILL,
15 15
  or any signal specified with option --signal.
16 16
 
17 17
 # OPTIONS
18
+**--help**
19
+  Print usage statement
20
+
18 21
 **-s**, **--signal**="KILL"
19 22
    Signal to send to the container
20 23
 
... ...
@@ -6,6 +6,7 @@ docker-load - Load an image from a tar archive on STDIN
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker load**
9
+[**--help**]
9 10
 [**-i**|**--input**[=*INPUT*]]
10 11
 
11 12
 
... ...
@@ -15,6 +16,9 @@ Loads a tarred repository from a file or the standard input stream.
15 15
 Restores both images and tags.
16 16
 
17 17
 # OPTIONS
18
+**--help**
19
+  Print usage statement
20
+
18 21
 **-i**, **--input**=""
19 22
    Read from a tar archive file, instead of STDIN
20 23
 
... ...
@@ -7,6 +7,7 @@ docker-login - Register or log in to a Docker registry server, if no server is s
7 7
 # SYNOPSIS
8 8
 **docker login**
9 9
 [**-e**|**--email**[=*EMAIL*]]
10
+[**--help**]
10 11
 [**-p**|**--password**[=*PASSWORD*]]
11 12
 [**-u**|**--username**[=*USERNAME*]]
12 13
  [SERVER]
... ...
@@ -20,6 +21,9 @@ login to a private registry you can specify this by adding the server name.
20 20
 **-e**, **--email**=""
21 21
    Email
22 22
 
23
+**--help**
24
+  Print usage statement
25
+
23 26
 **-p**, **--password**=""
24 27
    Password
25 28
 
... ...
@@ -7,6 +7,7 @@ docker-logs - Fetch the logs of a container
7 7
 # SYNOPSIS
8 8
 **docker logs**
9 9
 [**-f**|**--follow**[=*false*]]
10
+[**--help**]
10 11
 [**-t**|**--timestamps**[=*false*]]
11 12
 [**--tail**[=*"all"*]]
12 13
 CONTAINER
... ...
@@ -22,6 +23,9 @@ The **docker logs --follow** command combines commands **docker logs** and
22 22
 then continue streaming new output from the container’s stdout and stderr.
23 23
 
24 24
 # OPTIONS
25
+**--help**
26
+  Print usage statement
27
+
25 28
 **-f**, **--follow**=*true*|*false*
26 29
    Follow log output. The default is *false*.
27 30
 
... ...
@@ -6,6 +6,7 @@ docker-port - Lookup the public-facing port that is NAT-ed to PRIVATE_PORT
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker port**
9
+[**--help**]
9 10
 CONTAINER PRIVATE_PORT
10 11
 
11 12
 # OPTIONS
... ...
@@ -8,6 +8,7 @@ docker-ps - List containers
8 8
 **docker ps**
9 9
 [**-a**|**--all**[=*false*]]
10 10
 [**--before**[=*BEFORE*]]
11
+[**--help**]
11 12
 [**-f**|**--filter**[=*[]*]]
12 13
 [**-l**|**--latest**[=*false*]]
13 14
 [**-n**[=*-1*]]
... ...
@@ -29,6 +30,9 @@ the running containers.
29 29
 **--before**=""
30 30
    Show only container created before Id or Name, include non-running ones.
31 31
 
32
+**--help**
33
+  Print usage statement
34
+
32 35
 **-f**, **--filter**=[]
33 36
    Provide filter values. Valid filters:
34 37
                           exited=<int> - containers with exit code of <int>
... ...
@@ -6,6 +6,7 @@ docker-pull - Pull an image or a repository from the registry
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker pull**
9
+[**--help**] 
9 10
 NAME[:TAG]
10 11
 
11 12
 # DESCRIPTION
... ...
@@ -16,9 +17,10 @@ images for that repository name are pulled down including any tags.
16 16
 It is also possible to specify a non-default registry to pull from.
17 17
 
18 18
 # OPTIONS
19
-There are no available options.
19
+**--help**
20
+  Print usage statement
20 21
 
21
-# EXAMPLES
22
+# EXAMPLE
22 23
 
23 24
 # Pull a repository with multiple images
24 25
 
... ...
@@ -6,6 +6,7 @@ docker-push - Push an image or a repository to the registry
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker push**
9
+[**--help**]
9 10
 NAME[:TAG]
10 11
 
11 12
 # DESCRIPTION
... ...
@@ -15,7 +16,8 @@ image can be pushed to another, perhaps private, registry as demonstrated in
15 15
 the example below.
16 16
 
17 17
 # OPTIONS
18
-There are no available options.
18
+**--help**
19
+  Print usage statement
19 20
 
20 21
 # EXAMPLES
21 22
 
... ...
@@ -6,6 +6,7 @@ docker-restart - Restart a running container
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker restart**
9
+[**--help**]
9 10
 [**-t**|**--time**[=*10*]]
10 11
  CONTAINER [CONTAINER...]
11 12
 
... ...
@@ -13,6 +14,9 @@ docker-restart - Restart a running container
13 13
 Restart each container listed.
14 14
 
15 15
 # OPTIONS
16
+**--help**
17
+  Print usage statement
18
+
16 19
 **-t**, **--time**=10
17 20
    Number of seconds to try to stop for before killing the container. Once killed it will then be restarted. Default is 10 seconds.
18 21
 
... ...
@@ -19,6 +19,9 @@ remove a running container unless you use the \fB-f\fR option. To see all
19 19
 containers on a host use the **docker ps -a** command.
20 20
 
21 21
 # OPTIONS
22
+**--help**
23
+  Print usage statement
24
+
22 25
 **-f**, **--force**=*true*|*false*
23 26
    Force the removal of a running container (uses SIGKILL). The default is *false*.
24 27
 
... ...
@@ -7,6 +7,7 @@ docker-rmi - Remove one or more images
7 7
 # SYNOPSIS
8 8
 **docker rmi**
9 9
 [**-f**|**--force**[=*false*]]
10
+[**--help**]
10 11
 [**--no-prune**[=*false*]]
11 12
 IMAGE [IMAGE...]
12 13
 
... ...
@@ -21,6 +22,9 @@ use the **docker images** command.
21 21
 **-f**, **--force**=*true*|*false*
22 22
    Force removal of the image. The default is *false*.
23 23
 
24
+**--help**
25
+  Print usage statement
26
+
24 27
 **--no-prune**=*true*|*false*
25 28
    Do not delete untagged parents. The default is *false*.
26 29
 
... ...
@@ -21,6 +21,7 @@ docker-run - Run a command in a new container
21 21
 [**--env-file**[=*[]*]]
22 22
 [**--expose**[=*[]*]]
23 23
 [**-h**|**--hostname**[=*HOSTNAME*]]
24
+[**--help**]
24 25
 [**-i**|**--interactive**[=*false*]]
25 26
 [**--link**[=*[]*]]
26 27
 [**--lxc-conf**[=*[]*]]
... ...
@@ -132,6 +133,9 @@ developer can expose the port using the EXPOSE parameter of the Dockerfile, 2)
132 132
 the operator can use the **--expose** option with **docker run**, or 3) the
133 133
 container can be started with the **--link**.
134 134
 
135
+**--help**
136
+  Print usage statement
137
+
135 138
 **-h**, **--hostname**=*hostname*
136 139
    Sets the container host name that is available inside the container.
137 140
 
... ...
@@ -6,6 +6,7 @@ docker-save - Save an image to a tar archive (streamed to STDOUT by default)
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker save**
9
+[**--help**]
9 10
 [**-o**|**--output**[=*OUTPUT*]]
10 11
 IMAGE
11 12
 
... ...
@@ -16,6 +17,9 @@ parent layers, and all tags + versions, or specified repo:tag.
16 16
 Stream to a file instead of STDOUT by using **-o**.
17 17
 
18 18
 # OPTIONS
19
+**--help**
20
+  Print usage statement
21
+
19 22
 **-o**, **--output**=""
20 23
    Write to an file, instead of STDOUT
21 24
 
... ...
@@ -7,6 +7,7 @@ docker-search - Search the Docker Hub for images
7 7
 # SYNOPSIS
8 8
 **docker search**
9 9
 [**--automated**[=*false*]]
10
+[**--help**]
10 11
 [**--no-trunc**[=*false*]]
11 12
 [**-s**|**--stars**[=*0*]]
12 13
 TERM
... ...
@@ -22,6 +23,9 @@ is automated.
22 22
 **--automated**=*true*|*false*
23 23
    Only show automated builds. The default is *false*.
24 24
 
25
+**--help**
26
+  Print usage statement
27
+
25 28
 **--no-trunc**=*true*|*false*
26 29
    Don't truncate output. The default is *false*.
27 30
 
... ...
@@ -7,6 +7,7 @@ docker-start - Restart a stopped container
7 7
 # SYNOPSIS
8 8
 **docker start**
9 9
 [**-a**|**--attach**[=*false*]]
10
+[**--help**]
10 11
 [**-i**|**--interactive**[=*false*]]
11 12
 CONTAINER [CONTAINER...]
12 13
 
... ...
@@ -18,6 +19,9 @@ Start a stopped container.
18 18
 **-a**, **--attach**=*true*|*false*
19 19
    Attach container's STDOUT and STDERR and forward all signals to the process. The default is *false*.
20 20
 
21
+**--help**
22
+  Print usage statement
23
+
21 24
 **-i**, **--interactive**=*true*|*false*
22 25
    Attach container's STDIN. The default is *false*.
23 26
 
... ...
@@ -6,6 +6,7 @@ docker-stop - Stop a running container by sending SIGTERM and then SIGKILL after
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker stop**
9
+[**--help**]
9 10
 [**-t**|**--time**[=*10*]]
10 11
  CONTAINER [CONTAINER...]
11 12
 
... ...
@@ -14,6 +15,9 @@ Stop a running container (Send SIGTERM, and then SIGKILL after
14 14
  grace period)
15 15
 
16 16
 # OPTIONS
17
+**--help**
18
+  Print usage statement
19
+
17 20
 **-t**, **--time**=10
18 21
    Number of seconds to wait for the container to stop before killing it. Default is 10 seconds.
19 22
 
... ...
@@ -7,6 +7,7 @@ docker-tag - Tag an image into a repository
7 7
 # SYNOPSIS
8 8
 **docker tag**
9 9
 [**-f**|**--force**[=*false*]]
10
+[**--help**]
10 11
  IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
11 12
 
12 13
 # DESCRIPTION
... ...
@@ -6,6 +6,7 @@ docker-top - Display the running processes of a container
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker top**
9
+[**--help**]
9 10
 CONTAINER [ps OPTIONS]
10 11
 
11 12
 # DESCRIPTION
... ...
@@ -14,7 +15,8 @@ Look up the running process of the container. ps-OPTION can be any of the
14 14
  options you would pass to a Linux ps command.
15 15
 
16 16
 # OPTIONS
17
-There are no available options.
17
+**--help**
18
+  Print usage statement
18 19
 
19 20
 # EXAMPLES
20 21
 
... ...
@@ -6,6 +6,7 @@ docker-wait - Block until a container stops, then print its exit code.
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker wait**
9
+[**--help**]
9 10
 CONTAINER [CONTAINER...]
10 11
 
11 12
 # DESCRIPTION
... ...
@@ -13,7 +14,8 @@ CONTAINER [CONTAINER...]
13 13
 Block until a container stops, then print its exit code.
14 14
 
15 15
 # OPTIONS
16
-There are no available options.
16
+**--help**
17
+  Print usage statement
17 18
 
18 19
 # EXAMPLES
19 20
 
... ...
@@ -26,6 +26,9 @@ To see the man page for a command run **man docker <command>**.
26 26
 **-D**=*true*|*false*
27 27
    Enable debug mode. Default is false.
28 28
 
29
+**--help**
30
+  Print usage statement
31
+
29 32
 **-H**, **--host**=[unix:///var/run/docker.sock]: tcp://[host:port] to bind or
30 33
 unix://[/path/to/socket] to use.
31 34
    The socket(s) to bind to in daemon mode specified using one or more
... ...
@@ -15,6 +15,19 @@ or execute `docker help`:
15 15
 
16 16
       ...
17 17
 
18
+## Help
19
+To list the help on any command just execute the command, followed by the `--help` option.
20
+
21
+    $ sudo docker run --help
22
+
23
+    Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
24
+
25
+    Run a command in a new container
26
+
27
+      -a, --attach=[]            Attach to STDIN, STDOUT or STDERR.
28
+      -c, --cpu-shares=0         CPU shares (relative weight)
29
+    ...
30
+
18 31
 ## Option types
19 32
 
20 33
 Single character commandline options can be combined, so rather than
... ...
@@ -395,6 +395,19 @@ func Lookup(name string) *Flag {
395 395
 	return CommandLine.formal[name]
396 396
 }
397 397
 
398
+func (f *FlagSet) BadArgs(nargs int) bool {
399
+	if NArg() < nargs {
400
+		fmt.Fprintf(f.out(), "docker: '%s' requires arguments. See 'docker %s --help'.\n", f.name, f.name)
401
+		return true
402
+	} else {
403
+		if nargs == 0 && NArg() != 0 {
404
+			fmt.Fprintf(f.out(), "docker: '%s' does not require arguments. See 'docker %s --help'.\n", f.name, f.name)
405
+			return true
406
+		}
407
+	}
408
+	return false
409
+}
410
+
398 411
 // Set sets the value of the named flag.
399 412
 func (f *FlagSet) Set(name, value string) error {
400 413
 	flag, ok := f.formal[name]
... ...
@@ -468,7 +481,7 @@ func defaultUsage(f *FlagSet) {
468 468
 // Usage prints to standard error a usage message documenting all defined command-line flags.
469 469
 // The function is a variable that may be changed to point to a custom function.
470 470
 var Usage = func() {
471
-	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
471
+	fmt.Fprintf(CommandLine.output, "Usage of %s:\n", os.Args[0])
472 472
 	PrintDefaults()
473 473
 }
474 474
 
... ...
@@ -757,7 +770,7 @@ func Var(value Value, names []string, usage string) {
757 757
 func (f *FlagSet) failf(format string, a ...interface{}) error {
758 758
 	err := fmt.Errorf(format, a...)
759 759
 	fmt.Fprintln(f.out(), err)
760
-	f.usage()
760
+	fmt.Fprintf(f.out(), "See 'docker %s --help'.\n", f.name)
761 761
 	return err
762 762
 }
763 763
 
... ...
@@ -3,6 +3,7 @@ package runconfig
3 3
 import (
4 4
 	"fmt"
5 5
 	"io/ioutil"
6
+	"os"
6 7
 	"path"
7 8
 	"strconv"
8 9
 	"strings"
... ...
@@ -75,6 +76,8 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
75 75
 		flNetMode         = cmd.String([]string{"-net"}, "bridge", "Set the Network mode for the container\n'bridge': creates a new network stack for the container on the docker bridge\n'none': no networking for this container\n'container:<name|id>': reuses another container network stack\n'host': use the host network stack inside the container.  Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.")
76 76
 		flRestartPolicy   = cmd.String([]string{"-restart"}, "", "Restart policy to apply when a container exits (no, on-failure[:max-retry], always)")
77 77
 		// For documentation purpose
78
+		help = cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
79
+
78 80
 		_ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxy received signals to the process (even in non-TTY mode). SIGCHLD, SIGSTOP, and SIGKILL are not proxied.")
79 81
 		_ = cmd.String([]string{"#name", "-name"}, "", "Assign a name to the container")
80 82
 	)
... ...
@@ -166,9 +169,14 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
166 166
 		entrypoint []string
167 167
 		image      string
168 168
 	)
169
-	if len(parsedArgs) >= 1 {
170
-		image = cmd.Arg(0)
169
+
170
+	if *help {
171
+		return nil, nil, cmd, nil
172
+	}
173
+	if cmd.BadArgs(1) {
174
+		os.Exit(1)
171 175
 	}
176
+	image = cmd.Arg(0)
172 177
 	if len(parsedArgs) > 1 {
173 178
 		runCmd = parsedArgs[1:]
174 179
 	}