package container import ( "io" "github.com/docker/docker/api/types" "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" "github.com/docker/docker/pkg/stdcopy" "github.com/spf13/cobra" "golang.org/x/net/context" ) type logsOptions struct { follow bool since string timestamps bool details bool tail string container string } // NewLogsCommand creates a new cobra.Command for `docker logs` func NewLogsCommand(dockerCli *command.DockerCli) *cobra.Command { var opts logsOptions cmd := &cobra.Command{ Use: "logs [OPTIONS] CONTAINER", Short: "Fetch the logs of a container", Args: cli.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { opts.container = args[0] return runLogs(dockerCli, &opts) }, } flags := cmd.Flags() flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output") flags.StringVar(&opts.since, "since", "", "Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)") flags.BoolVarP(&opts.timestamps, "timestamps", "t", false, "Show timestamps") flags.BoolVar(&opts.details, "details", false, "Show extra details provided to logs") flags.StringVar(&opts.tail, "tail", "all", "Number of lines to show from the end of the logs") return cmd } func runLogs(dockerCli *command.DockerCli, opts *logsOptions) error { ctx := context.Background() options := types.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, Since: opts.since, Timestamps: opts.timestamps, Follow: opts.follow, Tail: opts.tail, Details: opts.details, } responseBody, err := dockerCli.Client().ContainerLogs(ctx, opts.container, options) if err != nil { return err } defer responseBody.Close() c, err := dockerCli.Client().ContainerInspect(ctx, opts.container) if err != nil { return err } if c.Config.Tty { _, err = io.Copy(dockerCli.Out(), responseBody) } else { _, err = stdcopy.StdCopy(dockerCli.Out(), dockerCli.Err(), responseBody) } return err }