@@ -672,6 +672,106 @@ public function containerUnpause($container)
672
672
)->then (array ($ this ->parser , 'expectEmpty ' ));
673
673
}
674
674
675
+ /**
676
+ * Attach to a container to read its output.
677
+ *
678
+ * This resolves with a string containing the container output, i.e. STDOUT
679
+ * and STDERR as requested.
680
+ *
681
+ * Keep in mind that this means the whole string has to be kept in memory.
682
+ * For a larger container output it's usually a better idea to use a streaming
683
+ * approach, see `containerAttachStream()` for more details.
684
+ * In particular, the same also applies for the `$stream` flag. It can be used
685
+ * to follow the container output as long as the container is running.
686
+ *
687
+ * Note that this endpoint internally has to check the `containerInspect()`
688
+ * endpoint first in order to figure out the TTY settings to properly decode
689
+ * the raw container output.
690
+ *
691
+ * @param string $container container ID
692
+ * @param bool $logs replay previous logs before attaching. Default false
693
+ * @param bool $stream continue streaming. Default false
694
+ * @param bool $stdout attach to stdout. Default true
695
+ * @param bool $stderr attach to stderr. Default true
696
+ * @return PromiseInterface Promise<string> container output string
697
+ * @link https://docs.docker.com/engine/api/v1.40/#operation/ContainerAttach
698
+ * @uses self::containerAttachStream()
699
+ * @see self::containerAttachStream()
700
+ */
701
+ public function containerAttach ($ container , $ logs = false , $ stream = false , $ stdout = true , $ stderr = true )
702
+ {
703
+ return $ this ->streamingParser ->bufferedStream (
704
+ $ this ->containerAttachStream ($ container , $ logs , $ stream , $ stdout , $ stderr )
705
+ );
706
+ }
707
+
708
+ /**
709
+ * Attach to a container to read its output.
710
+ *
711
+ * This is a streaming API endpoint that returns a readable stream instance
712
+ * containing the container output, i.e. STDOUT and STDERR as requested.
713
+ *
714
+ * This works for container output of arbitrary sizes as only small chunks have to
715
+ * be kept in memory.
716
+ *
717
+ * This is particularly useful for the `$stream` flag. It can be used to
718
+ * follow the container output as long as the container is running. Either
719
+ * the `$stream` or `$logs` parameter must be `true` for this endpoint to do
720
+ * anything meaningful.
721
+ *
722
+ * Note that by default the output of both STDOUT and STDERR will be emitted
723
+ * as normal "data" events. You can optionally pass a custom event name which
724
+ * will be used to emit STDERR data so that it can be handled separately.
725
+ * Note that the normal streaming primitives likely do not know about this
726
+ * event, so special care may have to be taken.
727
+ * Also note that this option has no effect if the container has been
728
+ * created with a TTY.
729
+ *
730
+ * Note that this endpoint internally has to check the `containerInspect()`
731
+ * endpoint first in order to figure out the TTY settings to properly decode
732
+ * the raw container output.
733
+ *
734
+ * Note that this endpoint intentionally does not expose the `$stdin` flag.
735
+ * Access to STDIN will be exposed as a dedicated API endpoint in a future
736
+ * version.
737
+ *
738
+ * @param string $container container ID
739
+ * @param bool $logs replay previous logs before attaching. Default false
740
+ * @param bool $stream continue streaming. Default false
741
+ * @param bool $stdout attach to stdout. Default true
742
+ * @param bool $stderr attach to stderr. Default true
743
+ * @param string $stderrEvent custom event to emit for STDERR data (otherwise emits as "data")
744
+ * @return ReadableStreamInterface container output stream
745
+ * @link https://docs.docker.com/engine/api/v1.40/#operation/ContainerAttach
746
+ * @see self::containerAttach()
747
+ */
748
+ public function containerAttachStream ($ container , $ logs = false , $ stream = false , $ stdout = true , $ stderr = true , $ stderrEvent = null )
749
+ {
750
+ $ parser = $ this ->streamingParser ;
751
+ $ browser = $ this ->browser ;
752
+ $ url = $ this ->uri ->expand (
753
+ '/containers/{container}/attach{?logs,stream,stdout,stderr} ' ,
754
+ array (
755
+ 'container ' => $ container ,
756
+ 'logs ' => $ this ->boolArg ($ logs ),
757
+ 'stream ' => $ this ->boolArg ($ stream ),
758
+ 'stdout ' => $ this ->boolArg ($ stdout ),
759
+ 'stderr ' => $ this ->boolArg ($ stderr )
760
+ )
761
+ );
762
+
763
+ // first inspect container to check TTY setting, then attach with appropriate log parser
764
+ return \React \Promise \Stream \unwrapReadable ($ this ->containerInspect ($ container )->then (function ($ info ) use ($ url , $ browser , $ parser , $ stderrEvent ) {
765
+ $ stream = $ parser ->parsePlainStream ($ browser ->withOptions (array ('streaming ' => true ))->post ($ url ));
766
+
767
+ if (!$ info ['Config ' ]['Tty ' ]) {
768
+ $ stream = $ parser ->demultiplexStream ($ stream , $ stderrEvent );
769
+ }
770
+
771
+ return $ stream ;
772
+ }));
773
+ }
774
+
675
775
/**
676
776
* Block until container id stops, then returns the exit code
677
777
*
0 commit comments