Запуск приложения внутри Docker как пользователя без полномочий root
После вчерашних новостей о Shocker, похоже, что приложения внутри контейнера Docker не должны запускаться с правами root. Я попытался обновить свой Dockerfile
, чтобы создать пользователя приложения, однако изменение прав доступа к файлам приложений (хотя и остается root) не работает. Я предполагаю, что это связано с тем, что некоторые разрешения LXC не предоставляются корневому пользователю, возможно?
Здесь мой файл Docker:
# Node.js app Docker file
FROM dockerfile/nodejs
MAINTAINER Thom Nichols "[email protected]"
RUN useradd -ms /bin/bash node
ADD . /data
# This next line doesn't seem to have any effect:
RUN chown -R node /data
ENV HOME /home/node
USER node
RUN cd /data && npm install
EXPOSE 8888
WORKDIR /data
CMD ["npm", "start"]
Довольно просто, но когда я ls -l
все еще принадлежит root:
[ [email protected]:/data {docker-nonroot-user} ]$ ls -l /data
total 64K
-rw-r--r-- 1 root root 383 Jun 18 20:32 Dockerfile
-rw-r--r-- 1 root root 862 Jun 18 16:23 Gruntfile.js
-rw-r--r-- 1 root root 1.2K Jun 18 15:48 README.md
drwxr-xr-x 4 root root 4.0K May 30 14:24 assets/
-rw-r--r-- 1 root root 416 Jun 3 14:22 bower.json
-rw-r--r-- 1 root root 930 May 30 01:50 config.js
drwxr-xr-x 4 root root 4.0K Jun 18 16:08 lib/
drwxr-xr-x 42 root root 4.0K Jun 18 16:04 node_modules/
-rw-r--r-- 1 root root 2.0K Jun 18 16:04 package.json
-rw-r--r-- 1 root root 118 May 30 18:35 server.js
drwxr-xr-x 3 root root 4.0K May 30 02:17 static/
drwxr-xr-x 3 root root 4.0K Jun 18 20:13 test/
drwxr-xr-x 3 root root 4.0K Jun 3 17:38 views/
Мой обновленный файл docker отлично работает благодаря @creak разъяснению того, как работают тома. Как только исходные файлы chown
ed, npm install
запускается как пользователь без полномочий root. И благодаря крючку postinstall
, npm запускает bower install && grunt assets
, который выполняет оставшиеся шаги установки и избегает необходимости npm install -g
любых node cli-инструментов, таких как bower, grunt или coffeescript.
Ответы
Ответ 1
Это немного сложно, на самом деле это связано с тем, с чего вы начинаете.
Если вы посмотрите на источник, вы заметите, что /data/
является томом. Итак, все, что вы делаете в Dockerfile
, будет отброшено и переопределено во время выполнения томом, который затем будет установлен.
Вы можете использовать его во время выполнения, изменив CMD на нечто вроде CMD chown -R node /data && npm start
.
Ответ 2
Отметьте это сообщение: http://www.yegor256.com/2014/08/29/docker-non-root.html В rultor.com мы запускаем все сборки в своих контейнерах Docker. И каждый раз перед запуском скриптов внутри контейнера мы переключаемся на пользователя без полномочий root. Вот как это делается:
adduser --disabled-password --gecos '' r
adduser r sudo
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
su -m r -c /home/r/script.sh
r
- пользователь, которого мы используем.
Ответ 3
Обновление 2015-09-28
Я заметил, что этот пост получил немного внимания. Слово совета для любого, кто потенциально заинтересован в том, чтобы делать что-то подобное. Я бы попытался использовать Python или другой язык в качестве оболочки для ваших script исполнений. Выполнение собственных скриптов bash У меня были проблемы при попытке передать множество аргументов моим контейнерам. В частности, были проблемы с интерпретацией/экранированием символов "и" оболочкой.
Мне нужно было изменить пользователя по несколько иной причине.
Я создал изображение докеры с полнофункциональной установкой ImageMagick и Ffmpeg с желанием, чтобы я мог делать преобразования на изображениях/видео в моей ОС хоста. Моя проблема была в том, что это инструменты командной строки, поэтому немного сложнее выполнить их через докер, а затем вернуть результаты в ОС хоста. Мне удалось это сделать, установив объем докеров. Казалось, что это работает нормально, за исключением того, что вывод изображения/видео выводится как принадлежащий root (т.е. Пользовательский контейнер докеров), а не пользователь, выполнивший команду.
Я рассмотрел подход, который @François Zaninotto упомянул в своем ответе (вы можете увидеть полный make script здесь). Это было действительно здорово, но я предпочел вариант создания оболочки bash script, которую я бы зарегистрировал на своем пути. Я взял некоторые из концепций из подхода Makefile (в частности, создание пользователя/группы), а затем создал оболочку script.
Вот пример моей оболочки dockermagick script:
#!/bin/bash
### VARIABLES
DOCKER_IMAGE='acleancoder/imagemagick-full:latest'
CONTAINER_USERNAME='dummy'
CONTAINER_GROUPNAME='dummy'
HOMEDIR='/home/'$CONTAINER_USERNAME
GROUP_ID=$(id -g)
USER_ID=$(id -u)
### FUNCTIONS
create_user_cmd()
{
echo \
groupadd -f -g $GROUP_ID $CONTAINER_GROUPNAME '&&' \
useradd -u $USER_ID -g $CONTAINER_GROUPNAME $CONTAINER_USERNAME '&&' \
mkdir --parent $HOMEDIR '&&' \
chown -R $CONTAINER_USERNAME:$CONTAINER_GROUPNAME $HOMEDIR
}
execute_as_cmd()
{
echo \
sudo -u $CONTAINER_USERNAME HOME=$HOMEDIR
}
full_container_cmd()
{
echo "'$(create_user_cmd) && $(execute_as_cmd) [email protected]'"
}
### MAIN
eval docker run \
--rm=true \
-a stdout \
-v $(pwd):$HOMEDIR \
-w $HOMEDIR \
$DOCKER_IMAGE \
/bin/bash -ci $(full_container_cmd [email protected])
Этот script привязан к изображению 'acleancoder/imagemagick-full', но его можно изменить, отредактировав переменную в верхней части script.
В основном это означает:
- Создайте идентификатор пользователя и группу в контейнере, чтобы он соответствовал пользователю, который выполняет script из основной ОС.
- Подключает текущий рабочий каталог ОС хоста (с использованием тонов докеров) в домашний каталог для пользователя, которого мы создаем в исполняемом контейнере докеров.
- Устанавливает каталог tmp как рабочий каталог для контейнера.
- Пропускает любые аргументы, которые передаются в script, которые затем будут выполняться с помощью '/bin/bash' исполняемого контейнера докеров.
Теперь я могу запускать команды ImageMagick/Ffmpeg против файлов на моей ОС хоста. Например, скажем, я хочу преобразовать изображение MyImage.jpeg в PNG файл, теперь я могу сделать следующее:
$ cd ~/MyImages
$ ls
MyImage.jpeg
$ dockermagick convert MyImage.jpeg Foo.png
$ ls
Foo.png MyImage.jpeg
Я также привязался к "stdout", поэтому я мог запустить команду идентификации ImageMagick, чтобы получить информацию об изображении на моем хосте, например:
$ dockermagick identify MyImage.jpeg
MyImage.jpeg JPEG 640x426 640x426+0+0 8-bit DirectClass 78.6KB 0.000u 0:00.000
Существуют очевидные опасности для установки текущего каталога и разрешения любого произвольного определения команды для выполнения. Но есть много способов сделать script более безопасным/безопасным. Я выполняю это в своей собственной непроизводственной личной среде, поэтому для меня это не очень важно. Но я настоятельно рекомендую вам принять во внимание опасность, если вы решите расширить этот script. Также стоит упомянуть, что этот script не учитывает хост OS X. make file, в котором я ворую идеи/концепции, учитывает это, поэтому вы можете расширить этот script, чтобы сделать это.
Еще одно ограничение на то, что я могу ссылаться только на файлы, находящиеся в настоящее время на пути, для которого я выполняю script. Это связано с тем, как я монтирую тома, поэтому следующее не будет работать:
$ cd ~/MyImages
$ ls
MyImage.jpeg
$ dockermagick convert ~/DifferentDirectory/AnotherImage.jpeg Foo.png
$ ls
MyImage.jpeg
Лучше всего просто перейти в каталог, содержащий изображение, и выполнить его непосредственно. Конечно, я уверен, что есть способы обойти это ограничение, но для меня и моих текущих потребностей это будет делать.
Ответ 4
Примечание. Я отвечаю здесь, потому что, учитывая общий заголовок, этот вопрос появляется в Google, когда вы ищете решение для "Запуск приложения внутри Docker как пользователя без полномочий root". Надеюсь, это поможет тем, кто оказался здесь.
С помощью Alpine Linux вы можете создать системного пользователя следующим образом:
RUN adduser -D -H -S -s /bin/false -u 1000 myuser
Все в Dockerfile
после этой строки выполняется с помощью myuser
.
myuser
пользователь имеет:
- не назначен пароль
- no home dir
- no login shell
- нет доступа root.
Это от adduser --help
:
-h DIR Home directory
-g GECOS GECOS field
-s SHELL Login shell
-G GRP Add user to existing group
-S Create a system user
-D Don't assign a password
-H Don't create home directory
-u UID User id
-k SKEL Skeleton directory (/etc/skel)
Ответ 5
Примечание. Этот ответ дан, потому что многие люди, ищущие использование без полномочий root, получат здесь. Остерегайтесь, это не устраняет проблему, вызвавшую проблему, но обращается к заголовку и пояснению к ответу, заданному @yegor256, который использует пользователя без полномочий root внутри контейнера. В этом ответе объясняется, как это сделать для варианта использования не-debian/non-ubuntu. Это не проблема с томами.
В системах на базе Red Hat, таких как Fedora и CentOS, это можно сделать следующим образом:
RUN adduser user && \
echo "user ALL=(root) NOPASSWD:ALL" | tee -a /etc/sudoers.d/user && \
chmod 0440 /etc/sudoers.d/user
В вашем Dockerfile вы можете запускать команды как этот пользователь, делая:
RUN su - user -c "echo Hello $HOME"
И команда может быть запущена как:
CMD ["su","-","user","-c","/bin/bash"]
Пример этого можно найти здесь:
https://github.com/gbraad/docker-dev/commit/644c51002f4b8e6fe5bb745638542a4c3d908b16