container_logs.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package client
  2. import (
  3. "io"
  4. "net/url"
  5. "time"
  6. "golang.org/x/net/context"
  7. "github.com/docker/docker/api/types"
  8. timetypes "github.com/docker/docker/api/types/time"
  9. )
  10. // ContainerLogs returns the logs generated by a container in an io.ReadCloser.
  11. // It's up to the caller to close the stream.
  12. //
  13. // The stream format on the response will be in one of two formats:
  14. //
  15. // If the container is using a TTY, there is only a single stream (stdout), and
  16. // data is copied directly from the container output stream, no extra
  17. // multiplexing or headers.
  18. //
  19. // If the container is *not* using a TTY, streams for stdout and stderr are
  20. // multiplexed.
  21. // The format of the multiplexed stream is as follows:
  22. //
  23. // [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT}
  24. //
  25. // STREAM_TYPE can be 1 for stdout and 2 for stderr
  26. //
  27. // SIZE1, SIZE2, SIZE3, and SIZE4 are four bytes of uint32 encoded as big endian.
  28. // This is the size of OUTPUT.
  29. //
  30. // You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this
  31. // stream.
  32. func (cli *Client) ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) {
  33. query := url.Values{}
  34. if options.ShowStdout {
  35. query.Set("stdout", "1")
  36. }
  37. if options.ShowStderr {
  38. query.Set("stderr", "1")
  39. }
  40. if options.Since != "" {
  41. ts, err := timetypes.GetTimestamp(options.Since, time.Now())
  42. if err != nil {
  43. return nil, err
  44. }
  45. query.Set("since", ts)
  46. }
  47. if options.Until != "" {
  48. ts, err := timetypes.GetTimestamp(options.Until, time.Now())
  49. if err != nil {
  50. return nil, err
  51. }
  52. query.Set("until", ts)
  53. }
  54. if options.Timestamps {
  55. query.Set("timestamps", "1")
  56. }
  57. if options.Details {
  58. query.Set("details", "1")
  59. }
  60. if options.Follow {
  61. query.Set("follow", "1")
  62. }
  63. query.Set("tail", options.Tail)
  64. resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil)
  65. if err != nil {
  66. return nil, wrapResponseError(err, resp, "container", container)
  67. }
  68. return resp.body, nil
  69. }