воскресенье, 13 апреля 2025 г.

наблюдения по использованию s6-overlay

Я когда то слышал, что vmvare решила вскочить на волну докеризации с неожиданной стороны: безопасности и продажи поддержки собственных образов. Ну и натыкался на тред об использовании non-root пользователя внутри docker контейнера. Так что в какой то момент для селф-хостинга [на антресоли] я созрел для испробования не рутового запуска в контейнере, потому что там была тонна питонячего и node.js кода.

Дело по сборке и тестированию образа c dumb-init шло и в какой то момент случилась оказия с прокидыванием каталога не рутового пользователя в хост другому не рутовомоу пользователю.
Я практически дословно повторил все проблемы из статьи про такие проблемы (веб архив).

Штош. Можно было загуглить как правильно прокидывать переменные окружения, обрабатывать их в энтрипоинте и в нем же делать множество присяданий: создавать пользователя с нужный uid'ом, менять права всех нужных каталогов и тому подобное. Можно было, зря этого не сделал.

 На этом моменте я вспомнил, что уже года 3 использовал qbittorrent контейнер от linuxserver и он прекрасно себя показал с правами доступа и к конфигам и к медиаданным. При этом в его репе был весьма минималистиыный Dockerfile а энтрипоинта не было как такогового.

Оказалось там для выравнивания прав владения используется какая то странная команда `lsiown` внутри каких то странных инит скриптов. Там еще и странные run скрипты были, с какой то exec.
Что поделать, я все равно видел s6 в сравнении запускалок и супервизоров. Тогда он показался мне монструозным в сравнении dumb-init. Но его решил присмотреться к нему, раз он такой любимчик "неизвестной" аудитории. Но момент настал.

Стоит конечно почитать для общего развития https://skarnet.org/software/s6/overview.html там описывается боль, страдание и превозмогание. Но можно пропустить и начать с гитхаб репы, во первых там будет выжимка, во вторых там будут прямые референсы на нужные разделы. Например раздел в readme ссылается на https://skarnet.org/software/s6-rc/s6-rc-compile.html и почему именно там описано что в какие каталоги надо раскладывать.

 Но документация все равно тяжелая c лишними реверансами, а местами скудная - нет рецетов или хаутушек. Так что будем подглядывать в несколько источников

 И по аналогии подпготовим конфиг для запуска https://mopidy.com/

# делаем референс на пользовательский конфиг
mkdir -p root/etc/s6-overlay/s6-rc.d/init-config-end/dependencies.d \
  && touch "$_"/init-mopidy-config
# чуть срежем пути в командах
cd root/etc/s6-overlay/s6-rc.d/

# управление зависимостями сервиса: запускаем в конце конфигурирования s6
mkdir -p init-mopidy-config/dependencies.d \
  && touch "$_"/init-config

# тип сервиса: разок запустить конфигурирование при старте
echo oneshot > init-mopidy-config/type

cat <<\EOF > init-mopidy-config/up
/etc/s6-overlay/s6-rc.d/init-mopidy-config/run
EOF

# по сути все теже башизмы, но рассованные по конвенции s6
# и в данном случае еще и пробрасываются переменные окружения 
# из билд стадии используя with-contenv
cat << \EOF > init-mopidy-config/run
#!/usr/bin/with-contenv bash
# shellcheck shell=bash

# make our default folders
mkdir -p \
  /config/mopidy \
  /app_data/cache \ 
  /data/music

# copy default config
if [[ ! -f /config/mopidy/mopidy.conf ]]; then
  cp /mopidy/mopidy.conf /config/mopidy/mopidy.conf
fi

# hacks for iris 
## webui local scan command
ln -s /config/mopidy/mopidy.conf /config/mopidy.conf
## не сработает проброс переменных окружения
# export IRIS_CONFIG_LOCATION=/config/mopidy/mopidy.conf
## а вот так сработает
printf "/config/mopidy/mopidy.conf" > \
  /var/run/s6/container_environment/IRIS_CONFIG_LOCATION

# permissions
lsiown -R abc:abc \
  /config \
  /usr_data \
  /data
EOF

chmod +x init-mopidy-config/up

# управление зависимостями целевого сервиса:
## нужно добавить в дерево зависимостей
mkdir -p svc-mopidy/dependencies.d && touch "$_"/init-services
echo 3 > svc-mopidy/notification-fd
echo longrun > svc-mopidy/type

# по сути энтрипоинт, но рассованный по конвенции s6
cat << \ENTRYPOINT_END > svc-mopidy/run
#!/usr/bin/with-contenv bash
# shellcheck shell=bash

exec \
  s6-notifyoncheck -d -n 300 -w 1000 -c "nc -z localhost 6680" \
  s6-setuidgid abc mopidy --config /config/mopidy/mopidy.conf
ENTRYPOINT_END

chmod +x svc-mopidy/run

# стартануть перечисленные сервисы после старта контейнера
mkdir -p user/contents.d \
  && touch "$_"/init-mopidy-config "$_"/svc-mopidy

Какие есть приколы? Да их много, у вас просто не соберется базовый sctratc или alpine с такими конфигами. Сейчас нырнем в приколы поглубже.

Файловая конфигурация

Дерево зависимостей сервисов строится файлами. Файлами, карл в 2024 году. И при этом нет какой либо консольного визарда, что бы он спросил пару вопросов и сам раскидал файлы по каталогам. Сам ручками через консоль ну или UI редактора проетка.
В примере выше, в каталоге сервиса `svc-mopidy` есть каталог зависимостей, вот там то и указывается кто должен быть запущен раньше. Это выглядит диковато во время описания сервисов через yaml-dsl в наше время.

Но автор прямо говорит, никаких конфигов и состояний гонки, если кто-нибудь захочет эти конфиги поменят в рантайме сервиса. Отмазка выглядит странной, так то и каталоги можно удалить в рантайме.
Я склоняюсь к тому, что автор хиккан, потому что сервисные каталоги утилиты можно прочитать при старте контейнера а потом просто забить на изменения. 


Раны дожны быть исполняемые

Казалось бы, все логично. Но если ты делаешь сраное дерево через консоль, то забываешь что кому то там нужно биты доступа поменять на +x.
Нужно бдить.

Переменные окружения наступают на мазоль файлового описания

Переменнае пробрасывается из докерфайла во все скрипты, что run, что инит. Тут можно спать спокойно, ноо только есть специальная инструкция в шибанге `#!/command/with-contenv sh` у каждого скрипта.

Не может не радовать, что в ридми они описана коряво, стоит подсмотреть в сборках linuxserver того же qbittorrent: `#!/usr/bin/with-contenv bash`.

Но если пытаться экспортировать переменную в инит скприте, в сервисном скрипте она не будет доступна без специального присядания с созданием файла переменной. Снова созданием файла, Карл!

 Автор этой балалайки посчитал, что нужно делать изоляцию запуска сервисных скриптов и по этому нужно изворачиваться. А половина команд запуска, которые я видел содержат аргумены с расположением конфиг файла.
Ладно, можно понять, что это красиво точно разделять инит стадию от исполняемой и пробрасывать исключительный минимум. Но цена за это - геморрой, часы отладки и изучения среды запуска, что бы понять что ей там не хватает. Сурово по сравнению с dump-init.

Автор кстати предлагатет и альтернативу: создание цепочки запуска, но лучше даже не вникать. Народ на них забил и костыляет по своему:

логгирование не втуда

У него они там сервисы в stderr пишут по умолчанию, удачи в изучении логов если забыли поманипулировать потоками.

Интератикция подломана

Отдельного упомнинания стоит предупреждение сломанности интерактивного режима: не стоит запускать в режиме `-it`, мол скорее всего не выйдете потом и вообще с сигналами будем беда.
Но не велика беда, для отладки на локалхосте, просто останавливаете контейнер любым удобным способом.
А после починки всех проблем и ош+cибок, по ctrl+c консоль уже спокойно отпускает.

Отказ от исправлений пермиссий в рантайме

Автор бубнит , что раньше был не прав а вот теперь познал истину: все пермисси задавайте на билд стадии в докерфайле. Потому что вам следует хорошо знать окружение уже на этапе сборки.
И это ни разу не бьется со всеми сборками на linuserver: все, абсолютно все, в инит стадии фиксят права доступа. И даже пишут свои костыльки (например  lsiown) что бы удобнее было отлаживать проблемы с правами досутпа.
У меня просто нет слов. 

Мой выбор - использовать lsiobase/alpine потому что они подумали о большей части проблем.

Выводы

Не надо туда лезть, если не чуствуете какого то особого жжения, скорее всего вам поможет dumb-init c километровым башизомом и вы сэкономите неделю вечеров. Ни или что вы там нашли.
Автор утилиты явно не догадывается как используется его супервизор и что создатели сборок зачастую то и не знают всех подробностей по запуску их образов. Почему то у него свой особенный взгляд на мир - все намертво хардкодить в докерфайле.
По этому костылят в linuxserver.io и если очень потребовалость, то стоит использовать именно их базовые образы и их примеры конфигурации сервисов в образе.
Самостоятельно по офф спекам написать докер сборку из голого scratch или не дай бог встроить в хостовую систему - практически не выполнимая задача. Какой то чувак на реддите писал что потратил 3 месяца и система все равно внезапно вылетает.

Комментариев нет :

Отправить комментарий