Как отправить в stdin контейнера docker-py?

Учитывая этот пример оболочки:

echo "hello" | docker run --rm -ti  -a stdin busybox \
    /bin/sh -c "cat - >/out"

Это выполнит контейнер busybox и создаст новый файл /out с содержимым hello.

Как бы это сделать с помощью docker-py?

Эквивалент docker-py:

container = docker_client.create_container( 'busybox',
                                            stdin_open = True,
                                            command    = 'sh -c "cat - >/out"'
                                            )
docker_client.start( container )

Существует stdin_open = True, но где я пишу 'hello'?

Ответ 1

В то время было невозможно прикрепить stdin к запущенному контейнеру. Это изменилось.

С текущей версией docker-py это теперь как-то возможно (aka slix обходной путь). Это взято из обсуждения на GitHub, который ориентирован на python 2.7.

См. этот пример в python 3 с версией docker-py версии 3.1.1

import docker, tarfile
from io import BytesIO

def test_send_data_via_stdin_into_container():
    client = docker.APIClient()

    # create container
    container = client.create_container(
        'busybox',
        stdin_open = True,
        command    = 'sh -c "cat - >/received.txt"')
    client.start(container)

    # attach stdin to container and send data
    original_text_to_send = 'hello this is from the other side'
    s = client.attach_socket(container, params={'stdin': 1, 'stream': 1})
    s._sock.send(original_text_to_send.encode('utf-8'))
    s.close()

    # stop container and collect data from the testfile
    client.stop(container)
    client.wait(container)
    raw_stream,status = client.get_archive(container,'/received.txt')
    tar_archive = BytesIO(b"".join((i for i in raw_stream)))
    t = tarfile.open(mode='r:', fileobj=tar_archive)
    text_from_container_file = t.extractfile('received.txt').read().decode('utf-8')
    client.remove_container(container)

    # check for equality
    assert text_from_container_file == original_text_to_send

if __name__ == '__main__':
    test_send_data_via_stdin_into_container()

Ответ 2

Вот обновленное решение:

#!/usr/bin/env python
import docker

# connect to docker
client = docker.APIClient()

# create a container
container = docker_client.create_container(
  'busybox',
  stdin_open = True,
  command    = 'sh -c "cat - >/out"')
client.start(container)

# attach to the container stdin socket
s = client.attach_socket(container, params={'stdin': 1, 'stream': 1})

# send text
s.send('hello')

# close, stop and disconnect
s.close()
client.stop(container)
client.wait(container)
client.remove_container(container)

Ответ 3

Вам нужно прикрепить к контейнеру, пока он работает для потока STDOUT/STDERR. Вот как:

container = docker_client.create_container('busybox',
                                        stdin_open = True,
                                        command    = 'sh -c "cat - >/)
docker_client.start(container)
out_stream = docker_client.attach(container=container, stdout=True,
                                  stderr=True, stream=True)

out_stream является generator, если у вас есть stream=True, поэтому вы можете перебирать его и получать журналы в режиме реального времени.

Подробнее: http://docker-py.readthedocs.org/en/latest/api/