Запуск приложения внутри Докер как не-root пользователя


после вчерашние новости шокера, похоже, что приложения внутри контейнера Docker не должны запускаться как root. Я пытался обновить мой Dockerfile чтобы создать пользователя приложения, однако изменение разрешений на файлы приложений (в то время как все еще root), похоже, не работает. Я предполагаю, что это связано с тем, что некоторые разрешения LXC не предоставляются пользователю root, возможно?

вот мой Dockerfile:

# Node.js app Docker file

FROM dockerfile/nodejs
MAINTAINER Thom Nichols "thom@thomnichols.org"

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:

[ node@ed7ae33e76e1:/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/

мой обновленный dockerfile отлично работает благодаря разъяснению @creak о том, как работают Тома. Как только начальные файлы chownЭд npm install выполняется от имени пользователя, не являющегося пользователем root. И благодаря postinstall крюк, НПМ работает bower install && grunt assets который заботится о оставшихся шагах установки и избегает любой необходимости npm install -g любые инструменты cli узла, такие как bower, grunt или coffeescript.

5 71

5 ответов:

Это немного сложнее, на самом деле из-за изображения начинаются от.

Если вы смотреть на источник, вы заметите, что /data/ - Это объем. Так что все, что вы делаете в Dockerfile будет отброшен и переопределен во время выполнения Томом, который затем монтируется.

вы можете chown во время выполнения, изменив свой CMD на что-то вроде CMD chown -R node /data && npm start.

проверьте это сообщение:http://www.yegor256.com/2014/08/29/docker-non-root.html In 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 это пользователь, которого мы используем.

обновление 2015-09-28

Я заметил, что этот пост получает немного внимания. Один совет для тех, кто потенциально заинтересован в том, чтобы сделать что-то подобное. Я попытаюсь использовать Python или другой язык в качестве оболочки для выполнения скрипта. Выполнение собственных сценариев bash у меня были проблемы при попытке передать различные аргументы в мои контейнеры. В частности, были проблемы с интерпретацией / экранированием символов "и" ракушка.


мне нужно было изменить пользователя по немного другой причине.

Я создал Docker-образ расквартировывать полнофункциональную установку ImageMagick и Ffmpeg С желанием, чтобы я мог делать преобразования на изображениях/видео в моей ОС хоста. Моя проблема заключалась в том, что это инструменты командной строки, поэтому немного сложнее выполнить их через docker, а затем получить результаты обратно в ОС хоста. Я справился для этого необходимо установить том docker. Это, казалось, работало нормально, за исключением того, что выход изображения/видео выходил как принадлежащий root (т. е. пользователь контейнер docker был запущен как), а не пользователь, который выполнил команду.

Я посмотрел на подход, который @François Zaninotto упомянул в своем ответ (вы можете увидеть полный сценарий make здесь). Это было действительно круто, но я предпочел вариант создания bash сценарий оболочки, который я затем зарегистрирую на своем пути. Я взял некоторые концепции из подхода Makefile (в частности, создание пользователя/группы), а затем создал сценарий оболочки.

вот пример моего dockermagick shell-скрипт:

#!/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) $@'"
}

### MAIN

eval docker run \
    --rm=true \
    -a stdout \
    -v $(pwd):$HOMEDIR \
    -w $HOMEDIR \
    $DOCKER_IMAGE \
    /bin/bash -ci $(full_container_cmd $@)

этот скрипт привязан к изображению' acleancoder/imagemagick-full', но это можно изменить, отредактировав переменную в верхней части скрипта.

что он в основном делает это:

  • создайте идентификатор пользователя и группу в контейнер чтобы соответствовать пользователю, который выполняет скрипт от хоста.
  • установить текущий рабочий каталог хоста (используя Тома докера) в домашний каталог для пользователей, мы создаем в рамках выполнения докер контейнер.
  • задает каталог tmp в качестве рабочего каталога контейнер.
  • передает любые аргументы, которые передаются в скрипт, который потом будет исполняться ' / 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 identify, чтобы получить информацию об изображении на моем хосте, например:

$ dockermagick identify MyImage.jpeg
  MyImage.jpeg JPEG 640x426 640x426+0+0 8-bit DirectClass 78.6KB 0.000u 0:00.000

существует очевидная опасность монтирования текущего каталога и разрешения передачи любого произвольного определения команды для выполнения. Но есть также много способов сделать скрипт более безопасным / безопасным. Я выполняю это в своей собственной непроизводственной личной среде, поэтому они не имеют самое большое беспокойство за меня. Но я настоятельно рекомендую вам принять во внимание опасности, если вы решите расширить этот сценарий. Также стоит упомянуть, что этот скрипт не учитывает хост OS X. Элемент файл то, что я краду идеи/концепции, учитывает это, поэтому вы можете расширить этот скрипт для этого.

еще одно ограничение, чтобы отметить, что я могу ссылаться только на файлы в настоящее время в пути, для которого я выполняю сценарий. Это связано с тем, как я монтирую Тома, поэтому следующее не будет работать:

$ cd ~/MyImages
$ ls
  MyImage.jpeg
$ dockermagick convert ~/DifferentDirectory/AnotherImage.jpeg Foo.png
$ ls
  MyImage.jpeg

лучше всего просто перейти в каталог, содержащий изображение, и выполнить его непосредственно. Конечно, я уверен, что есть способы обойти это ограничение тоже, но для меня и моих текущих потребностей, это будет делать.

Примечание:я отвечаю здесь, потому что, учитывая общее название, этот вопрос появляется в google, когда вы ищете решение для "запуска приложения внутри Docker как некорневого пользователя". Надеюсь, это поможет тем, кто застрял здесь.

С альпийские Linux вы можете создать системного пользователя, как это:

RUN adduser -D -H -S -s /bin/false -u 1000 myuser

все Dockerfile после этой строки выполняется с myuser.

myuser пользователь имеет:

  • без пароля
  • нет дома реж
  • нет оболочки входа в систему
  • нет 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)

Примечание:этот ответ дается, потому что многие люди, ищущие некорневое использование, окажутся здесь. Будьте осторожны, это не решает проблему, которая вызвала проблему, но обращается к заголовку и разъяснению к ответу, данному @yegor256, который использует пользователя без root внутри контейнера. Этот ответ объясняет, как это сделать для не-debian/не-ubuntu use-case. Это не решает проблему с объемами.

на системах на основе 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