Подтвердить что ты не робот

Запуск приложения внутри 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.

4b9b3361

Ответ 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