commit.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package client
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/url"
  7. "github.com/docker/distribution/reference"
  8. "github.com/docker/docker/api/types"
  9. Cli "github.com/docker/docker/cli"
  10. "github.com/docker/docker/opts"
  11. flag "github.com/docker/docker/pkg/mflag"
  12. "github.com/docker/docker/registry"
  13. "github.com/docker/docker/runconfig"
  14. )
  15. // CmdCommit creates a new image from a container's changes.
  16. //
  17. // Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
  18. func (cli *DockerCli) CmdCommit(args ...string) error {
  19. cmd := Cli.Subcmd("commit", []string{"CONTAINER [REPOSITORY[:TAG]]"}, Cli.DockerCommands["commit"].Description, true)
  20. flPause := cmd.Bool([]string{"p", "-pause"}, true, "Pause container during commit")
  21. flComment := cmd.String([]string{"m", "-message"}, "", "Commit message")
  22. flAuthor := cmd.String([]string{"a", "-author"}, "", "Author (e.g., \"John Hannibal Smith <hannibal@a-team.com>\")")
  23. flChanges := opts.NewListOpts(nil)
  24. cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image")
  25. // FIXME: --run is deprecated, it will be replaced with inline Dockerfile commands.
  26. flConfig := cmd.String([]string{"#-run"}, "", "This option is deprecated and will be removed in a future version in favor of inline Dockerfile-compatible commands")
  27. cmd.Require(flag.Max, 2)
  28. cmd.Require(flag.Min, 1)
  29. cmd.ParseFlags(args, true)
  30. var (
  31. name = cmd.Arg(0)
  32. repositoryAndTag = cmd.Arg(1)
  33. repositoryName string
  34. tag string
  35. )
  36. //Check if the given image name can be resolved
  37. if repositoryAndTag != "" {
  38. ref, err := reference.ParseNamed(repositoryAndTag)
  39. if err != nil {
  40. return err
  41. }
  42. if err := registry.ValidateRepositoryName(ref); err != nil {
  43. return err
  44. }
  45. repositoryName = ref.Name()
  46. switch x := ref.(type) {
  47. case reference.Digested:
  48. return errors.New("cannot commit to digest reference")
  49. case reference.Tagged:
  50. tag = x.Tag()
  51. }
  52. }
  53. v := url.Values{}
  54. v.Set("container", name)
  55. v.Set("repo", repositoryName)
  56. v.Set("tag", tag)
  57. v.Set("comment", *flComment)
  58. v.Set("author", *flAuthor)
  59. for _, change := range flChanges.GetAll() {
  60. v.Add("changes", change)
  61. }
  62. if *flPause != true {
  63. v.Set("pause", "0")
  64. }
  65. var (
  66. config *runconfig.Config
  67. response types.ContainerCommitResponse
  68. )
  69. if *flConfig != "" {
  70. config = &runconfig.Config{}
  71. if err := json.Unmarshal([]byte(*flConfig), config); err != nil {
  72. return err
  73. }
  74. }
  75. serverResp, err := cli.call("POST", "/commit?"+v.Encode(), config, nil)
  76. if err != nil {
  77. return err
  78. }
  79. defer serverResp.body.Close()
  80. if err := json.NewDecoder(serverResp.body).Decode(&response); err != nil {
  81. return err
  82. }
  83. fmt.Fprintln(cli.out, response.ID)
  84. return nil
  85. }