Comments 7
tl;dr stdout/stderr не умеют seek и возвращают ошибку, которую mariadb не может обработать. На то, чтобы это понять, ушло два дня.
По-моему в ошибке ясно написано, что случилось. Can't seek in file '/dev/stderr' (Errcode: 29 "Invalid seek")
Мускуль хочет сделать seek (вероятнее всего, на конец файла), а /dev/stderr справедливо возражает, что конца ошибкам нет.
Что делать? Писать патч, потому что весь интернет уверенно говорит, что нельзя из-за кривости мускуля. И дело тут не в правах.
Альтернативно - запускать sidecart, который будет реэкспортировать локальный ротируемый файл в stderr.
Статья оставляет желать лучшего. Местами полно голословных утверждений и неправильных выводов.
Однако тут есть странность: пользователю без root-прав все равно нужен
tty
для перенаправления вывода процесса (а, следовательно, и Docker-логов) в stdio.
TTY нужен только для взаимодействия с пользователем в интерактивном режиме, он не является обязательной составляющей для запуска приложений-демонов, вроде СУБД.
Без TTY внутри контейнера /proc/self/fd/{0..2} начинают ссылаться не на /dev/pts/0, а на pipe, который докер-демон на хосте сам читает и раскладывает в файлы с логами:
![](https://habrastorage.org/getpro/habr/upload_files/26d/ffe/cf3/26dffecf3909e18d82aeded8f57f193e.png)
В Alpine Linux писать в stdio могут только члены группы
tty
.
Владельцем файловых дескрипторов процесса становится пользователь, под которым он запущен. Например, на скриншоте выше я указал пользователя для запуска контейнера с помощью опции -u, и он стал владельцем stdout, как в случае с TTY, так и без него. И он без проблем может в него писать.
Вот только entrypoint различных СУБД, например mysql и postgres, запускаются под пользователем root. Это нужно, чтобы перед запуском непосредственно самого приложения исправить владельца папки с файлами БД и конфигами, а уже затем выполнить запуск СУБД с помощью su или sudo.
И тут действительно можно столкнуться с issue, на которое ссылается автор - без TTY владельцем pipe будет тот пользователь, под которым был запущен корневой процесс в контейнере, т.е. root. И так как это pipe, а не файл, к нему нельзя применить chown или chmod. Поэтому приходится использовать обходной вариант с TTY и добавлением пользователя в группу tty либо выполнением chmod o+g /dev/pts/0
Специальный Bash-скрипт может извлекать эти обычные файлы из запущенного контейнера с помощью команды копирования —
docker cp
Ага, по пути еще и изобретать свой logrotate вместо того, чтобы создать issue в репозиторий MariaDB.
Гораздо быстрее скачать исходники mariadb и посмотреть в исходный код в котором происходит ошибка ( файл sql/log.cc ) Более того, легко увидеть, что в случае pipe ситуация обрабатывается и в pipe логи писать можно.
is_fifo = my_stat(log_file_name, &f_stat, MYF(0)) &&
MY_S_ISFIFO(f_stat.st_mode);
...
if (is_fifo)
seek_offset= 0;
else if ((seek_offset= mysql_file_tell(file, MYF(MY_WME))))
goto err;
Далее, можно найти feature request для этого в жире mariadb https://jira.mariadb.org/browse/MDEV-6870 и создать подобный для character device, либо написать патч самому, либо извернуться и писать логи в pipe и настроить rsyslog, чтобы данные из пайпа отправлять куда нравится.
MySQL в Docker не может писать slow-логи в /dev/stderr