The stdout and stderr data from the container multiplexed into one stream of response from the Docker API.
    It follows the protocol described here https://docs.docker.com/engine/api/v1.30/#operation/ContainerAttach.
    The stream starts with a 8 byte header that contains the frame type and also payload size. Follwing that is the
    actual payload of given size. Once you read off this payload, we are ready to read the next header.

    This method will follow this protocol to read payload from the stream and return an iterator that returns
    a tuple containing the frame type and frame data. Callers can handle the data appropriately based on the frame
    type.

        Stdout => Frame Type = 1
        Stderr => Frame Type = 2


    Parameters
    ----------
    socket
        Socket to read responses from

    Yields
    -------
    int
        Type of the stream (1 => stdout, 2 => stderr)
    str
        Data in the stream

def _read_socket(socket):
    """
    The stdout and stderr data from the container multiplexed into one stream of response from the Docker API.
    It follows the protocol described here https://docs.docker.com/engine/api/v1.30/#operation/ContainerAttach.
    The stream starts with a 8 byte header that contains the frame type and also payload size. Follwing that is the
    actual payload of given size. Once you read off this payload, we are ready to read the next header.

    This method will follow this protocol to read payload from the stream and return an iterator that returns
    a tuple containing the frame type and frame data. Callers can handle the data appropriately based on the frame
    type.

        Stdout => Frame Type = 1
        Stderr => Frame Type = 2


    Parameters
    ----------
    socket
        Socket to read responses from

    Yields
    -------
    int
        Type of the stream (1 => stdout, 2 => stderr)
    str
        Data in the stream
    """

    # Keep reading the stream until the stream terminates
    while True:

        try:

            payload_type, payload_size = _read_header(socket)
            if payload_size < 0:
                # Something is wrong with the data stream. Payload size can't be less than zero
                break

            for data in _read_payload(socket, payload_size):
                yield payload_type, data

        except timeout:
            # Timeouts are normal during debug sessions and long running tasks
            LOG.debug("Ignoring docker socket timeout")

        except SocketError:
            # There isn't enough data in the stream. Probably the socket terminated
            break