Похоже, вы разрабатываете решение, очень похожее на то, которое я создал.Как упоминает ErikMD, не используйте gosu для переключения с пользователя на root, вы хотите пойти другим путем, от root к пользователю.В противном случае у вас будет открытая дыра в безопасности внутри вашего контейнера, чем любой пользователь сможет стать пользователем root, что отрицательно скажется на цели запуска контейнера под другим идентификатором пользователя.
Для решения, которое я собрал, яон будет работать независимо от того, запущен ли контейнер в рабочем режиме как пользователь без монтирования тома, или в процессе разработки с монтированием тома, изначально запустив контейнер с правами root.Вы можете иметь идентичный Dockerfile и изменить точку входа, чтобы иметь что-то вроде:
#!/bin/sh
if [ "$(id -u)" = "0" ]; then
fix-perms -r -u deploy -g deploy /var/www/${PROJECT_NAME}
exec gosu deploy "$@"
else
exec "$@"
fi
Сценарий fix-perms
выше из моего базового образа и включает в себя следующеенемного кода:
# update the uid
if [ -n "$opt_u" ]; then
OLD_UID=`getent passwd "${opt_u}" | cut -f3 -d:`
NEW_UID=`ls -nd "$1" | awk '{print $3}'`
if [ "$OLD_UID" != "$NEW_UID" ]; then
echo "Changing UID of $opt_u from $OLD_UID to $NEW_UID"
usermod -u "$NEW_UID" -o "$opt_u"
if [ -n "$opt_r" ]; then
find / -xdev -user "$OLD_UID" -exec chown -h "$opt_u" {} \;
fi
fi
fi
(Обратите внимание, мне действительно нравится, что вы используете stat -c
, и, вероятно, я буду обновлять мой сценарий fix-perms
, чтобы использовать его по сравнению с командой ls
, которая у меня там сейчас.)
Важной частью этого является запуск контейнера.Когда вам нужен код fix-perms
для запуска (который для меня только в разработке), я запускаю контейнер как root.Это может быть docker run -u root:root ...
или user: "root:root"
в файле композиции.Это изначально запускает контейнер как root, который запускает первую половину if / else в точке входа, которая запускает fix-perms
, а затем запускает gosu deploy
для перехода из root в развертывание перед вызовом "$ @", который является вашей командой (CMD).В результате pid 1 в контейнере выполняет команду от имени пользователя для развертывания.
В качестве отступления, если вам действительно нужен более простой способ запуска нескольких фрагментов точки входа таким образом, чтобы его было легкоВ дополнение к дочерним изображениям я использую папку entrypoint.d
, которая обрабатывается сценарием точки входа в моем базовом изображении.Код для реализации этой логики так же прост:
for ep in /etc/entrypoint.d/*.sh; do
if [ -x "${ep}" ]; then
echo "Running: ${ep}"
"${ep}"
fi
done
Все это можно увидеть вместе с примером использования nginx по адресу: https://github.com/sudo-bmitch/docker-base