Как запустить несколько сценариев входа один за другим внутри контейнера Docker? - PullRequest
0 голосов
/ 12 декабря 2018

Я пытаюсь сопоставить UID хоста с UID контейнера, как показано ниже.

Dockerfile

RUN addgroup -g 1000 deploy \
&& adduser -D -u 1000 -G deploy -s /bin/sh deploy

USER deploy

COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
CMD ["php-fpm7","-F"]

entrypoint.sh

whoami # it outputs `deploy`  

# Change UID of 'deploy' as per host user UID
HOST_CURRENT_USER_ID=$(stat -c "%u" /var/www/${PROJECT_NAME})
if [ ${HOST_CURRENT_USER_ID} -ne 0 ]; then
    gosu root usermod -u ${HOST_CURRENT_USER_ID} deploy
    gosu root groupmod -g ${HOST_CURRENT_USER_ID} deploy
fi

whoami  # It outputs as unknown user id 1000. 

Обратите внимание на вывод whoami выше.Даже если я изменил UID развертывания на host uid, процесс сценария точки входа не изменится, поскольку оболочка точки входа была вызвана UID 1000.

Поэтому я пришел к решению сделать две точки входапервый сценарий предназначен для изменения UID, а другой - для процесса начальной загрузки контейнера, который будет запущен в отдельной оболочке после изменения UID развертывания.Так как я могу заставить две точки входа работать за другой.Например, что-то вроде

ENTRYPOINT ["/fix-uid.sh && /entrypoint.sh"]

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Похоже, вы разрабатываете решение, очень похожее на то, которое я создал.Как упоминает 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

0 голосов
/ 13 декабря 2018

Поведение, которое вы наблюдаете, кажется вполне нормальным: в вашем сценарии точки входа вы изменили UID, связанный с именем пользователя deploy, но две команды whoami все еще выполняются с одним и тем же пользователем (идентифицированным UID в первомпоместите, а не имя пользователя.re-становиться root не является стандартной практикой (см., в частности, предупреждение в вышестоящем документе).

В вашем случае я бы предложил удалить команду и переключатель USER deployпользователь в самом конце, адаптируя скрипт точки входа следующим образом:

Dockerfile

(…)
RUN addgroup -g 1000 deploy \
&& adduser -D -u 1000 -G deploy -s /bin/sh deploy

COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
CMD ["php-fpm7","-F"]

entrypoint.sh

#!/bin/sh
whoami # it outputs `root`

# Change UID of 'deploy' as per host user UID
HOST_CURRENT_USER_ID=$(stat -c "%u" /var/www/${PROJECT_NAME})
if [ ${HOST_CURRENT_USER_ID} -ne 0 ]; then
    usermod -u ${HOST_CURRENT_USER_ID} deploy
    groupmod -g ${HOST_CURRENT_USER_ID} deploy
fi

# don't forget the "exec" builtin
exec gosu ${HOST_CURRENT_USER_ID}:${HOST_CURRENT_USER_ID} "$@"

это можно проверить с помощью id, например:

$ docker build -t test-gosu .
$ docker run --rm -it test-gosu /bin/sh
  $ id
...