logs.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package container
  2. import (
  3. "fmt"
  4. "io"
  5. "golang.org/x/net/context"
  6. "github.com/docker/docker/api/types"
  7. "github.com/docker/docker/cli"
  8. "github.com/docker/docker/cli/command"
  9. "github.com/docker/docker/pkg/stdcopy"
  10. "github.com/spf13/cobra"
  11. )
  12. var validDrivers = map[string]bool{
  13. "json-file": true,
  14. "journald": true,
  15. }
  16. type logsOptions struct {
  17. follow bool
  18. since string
  19. timestamps bool
  20. details bool
  21. tail string
  22. container string
  23. }
  24. // NewLogsCommand creates a new cobra.Command for `docker logs`
  25. func NewLogsCommand(dockerCli *command.DockerCli) *cobra.Command {
  26. var opts logsOptions
  27. cmd := &cobra.Command{
  28. Use: "logs [OPTIONS] CONTAINER",
  29. Short: "Fetch the logs of a container",
  30. Args: cli.ExactArgs(1),
  31. RunE: func(cmd *cobra.Command, args []string) error {
  32. opts.container = args[0]
  33. return runLogs(dockerCli, &opts)
  34. },
  35. }
  36. flags := cmd.Flags()
  37. flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output")
  38. flags.StringVar(&opts.since, "since", "", "Show logs since timestamp")
  39. flags.BoolVarP(&opts.timestamps, "timestamps", "t", false, "Show timestamps")
  40. flags.BoolVar(&opts.details, "details", false, "Show extra details provided to logs")
  41. flags.StringVar(&opts.tail, "tail", "all", "Number of lines to show from the end of the logs")
  42. return cmd
  43. }
  44. func runLogs(dockerCli *command.DockerCli, opts *logsOptions) error {
  45. ctx := context.Background()
  46. c, err := dockerCli.Client().ContainerInspect(ctx, opts.container)
  47. if err != nil {
  48. return err
  49. }
  50. if !validDrivers[c.HostConfig.LogConfig.Type] {
  51. return fmt.Errorf("\"logs\" command is supported only for \"json-file\" and \"journald\" logging drivers (got: %s)", c.HostConfig.LogConfig.Type)
  52. }
  53. options := types.ContainerLogsOptions{
  54. ShowStdout: true,
  55. ShowStderr: true,
  56. Since: opts.since,
  57. Timestamps: opts.timestamps,
  58. Follow: opts.follow,
  59. Tail: opts.tail,
  60. Details: opts.details,
  61. }
  62. responseBody, err := dockerCli.Client().ContainerLogs(ctx, opts.container, options)
  63. if err != nil {
  64. return err
  65. }
  66. defer responseBody.Close()
  67. if c.Config.Tty {
  68. _, err = io.Copy(dockerCli.Out(), responseBody)
  69. } else {
  70. _, err = stdcopy.StdCopy(dockerCli.Out(), dockerCli.Err(), responseBody)
  71. }
  72. return err
  73. }