Docker, запущенный с псевдо TTY (-t), дает мгновенный стандартный вывод, буферизация происходит без него
У меня есть пакет Python, который я запускаю внутри контейнера. Докерфайл говорит:
FROM frolvlad/alpine-python3
RUN apk --no-cache add ca-certificates
COPY ./ /app/
RUN cd app && python3 setup.py install
Теперь, когда образ собран, когда я запускаю его с помощью этой команды...
docker run --env-file ./envfile myimg sh -c 'myscript "$username" "$password"'
... требуется более минуты, чтобы увидеть какой-либо стандартный вывод. Я также должен остановить контейнер из другого терминала (Ctrl+C ничего не делает).
Но когда я запускаю изображение с помощью
docker run -t --env-file ./envfile myimg sh -c 'myscript "$username" "$password"'
(т.е. добавление -t
), он ведет себя как ожидалось (некоторые stdout каждые 5 секунд или около того).
В чем причина такого поведения? Я точно не знаю что -t
действительно, чтобы вызвать это, так как я не смог найти много документации об этом.
1 ответ
Это стандартное поведение Linux stdio.
Если вы выводите в файл или файловый дескриптор (например, stdout), он буферизуется порциями по 4 тыс. Это для оптимизации обработки ввода / вывода.
Если местом назначения является tty (терминал), буфер является линейным.
Ссылка: https://www.turnkeylinux.org/blog/unix-buffering
За кулисами виновна буферизация Unix stdio, реализованная в Linux посредством glibc, которая является системной библиотекой, которую большинство программ, реализованных на C, используют для обработки базовых вещей (например, IO).
Идея Unix-буферизации заключается в повышении производительности ввода-вывода путем объединения вызовов IO на уровне приложений (пользовательская область AKA) и, таким образом, минимизации относительно дорогих операций чтения / записи на уровне ядра.
По умолчанию запись в stdout проходит через 4096-байтовый буфер, если только stdout не является терминалом /tty, и в этом случае он буферизуется строкой.