web-dev-qa-db-ja.com

非ルートユーザーとしてDocker内でアプリを実行する

昨日のShockerのニュース の後、Dockerコンテナ内のアプリをrootとして実行すべきではないようです。 Dockerfileを更新してアプリユーザーを作成しようとしましたが、アプリファイルのアクセス許可を(まだrootに)変更しても機能しないようです。これは、おそらくLXCアクセス許可がルートユーザーに付与されていないためだと思いますか?

これが私のDockerfileです。

# 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するとき、すべてがまだルートによって所有されています:

[ 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がボリュームの仕組みを明確にしたおかげで。初期ファイルがchownedになると、npm installが非rootユーザーとして実行されます。 postinstallフックのおかげで、npmはbower install && grunt assetsを実行し、残りのインストール手順を処理し、npm install -g bower、grunt、coffeescriptなどのノードcliツールの必要性を回避します。

74
thom_nic

これは少し注意が必要です。実際には、元のイメージが原因です。

ソースを見る の場合、/data/はボリュームであることがわかります。したがって、Dockerfileで行うすべての操作は破棄され、実行時にマウントされたボリュームによってオーバーライドされます。

CMDをCMD chown -R node /data && npm startのようなものに変更することにより、実行時にchownできます。

14
creack

この投稿を確認してください: 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は、使用しているユーザーです。

26
yegor256

更新2015-09-28

この投稿が少し注目されていることに気付きました。このようなことをすることに潜在的に興味がある人のためのアドバイスの言葉。スクリプト実行のラッパーとしてPythonまたは別の言語を使用しようとします。ネイティブbashスクリプトの実行さまざまな引数をコンテナーに渡すときに問題が発生しました。具体的には、シェルによる「および」文字の解釈/エスケープに問題がありました。


少し異なる理由でユーザーを変更する必要がありました。

私はdocker imageを作成しましたImageMagickFfmpegのフル機能インストールを収容し、ホスト内の画像/ビデオの変換を行えるようにしたいOS。私の問題は、これらがコマンドラインツールであるため、ドッカーを介して実行し、結果をホストOSに戻すのが少し難しいことです。 Dockerボリュームをマウントすることでこれを可能にしました。これは、コマンドを実行したユーザーではなく、イメージ/ビデオ出力がroot(つまり、Dockerコンテナーを実行しているユーザー)によって所有されているとして出力されることを除いて、正常に機能するように見えました。

@FrançoisZaninottoが answer (完全なmakeスクリプト here で見ることができます)で言及しているアプローチを見ました。とてもクールでしたが、bash Shellスクリプトを作成して、パスに登録するオプションを選びました。 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」画像にバインドされていますが、スクリプトの上部にある変数を編集することで変更できます。

それが基本的にすることは:

  • ホストOSからスクリプトを実行するユーザーに一致するように、container内にユーザーIDとグループを作成します。
  • ホストOS(ドッカーボリュームを使用)の現在の作業ディレクトリを、実行中のドッカーコンテナ内で作成したユーザーのホームディレクトリにマウントします。
  • Tmpディレクトリをcontainerの作業ディレクトリとして設定します。
  • スクリプトに渡される引数を渡します。スクリプトは、実行中のdocker containerの '/ bin/bash'によって実行されます。

これで、ホストOS上のファイルに対してImageMagick/Ffmpegコマンドを実行できるようになりました。たとえば、画像MyImage.jpegPNGファイルに変換したい場合、次のようにできます。

$ 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

現在のディレクトリをマウントし、実行のために任意のコマンド定義を渡すことを許可することには明らかな危険があります。しかし、スクリプトをより安全/安全にするための多くの方法もあります。私はこれを自分の非生産的な個人環境で実行しているので、これらは私にとって最大の関心事ではありません。ただし、このスクリプトを拡張する場合は、危険性を考慮することを強くお勧めします。また、このスクリプトはOS Xホストを考慮に入れていないことを言及する価値があります。 make file 私がアイデア/概念を盗むのはこれを考慮に入れているので、このスクリプトを拡張することができます。

注意すべきもう1つの制限は、スクリプトを実行しているパスに現在あるファイルのみを参照できることです。これは、ボリュームをマウントする方法が原因であるため、以下は機能しません。

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

イメージを含むディレクトリに移動して、それに対して直接実行することをお勧めします。もちろん、この制限を回避する方法もあると確信していますが、私と現在のニーズについては、これで十分です。

18
ctrlplusb

「Docker内で非ルートとしてアプリを実行する」という解決策を探すと、一般的なタイトルが与えられ、この質問がGoogleにポップアップ表示されるため、ここで答えますユーザー"。ここで立ち往生している人々を助けることを願っています。

Alpine Linuxを使用すると、次のようなシステムユーザーを作成できます。

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

この行の後のDockerfile内のすべてがmyuserで実行されます。

myuserユーザーが持っているもの:

  • パスワードが割り当てられていません
  • nohomedir
  • ログインシェルなし
  • いいえ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)
3
Rotareti

この答えは、ルート以外の使用を探している多くの人々がここで終わるために与えられます。注意してください、これは問題の原因となった問題には対処していませんが、コンテナ内で非rootユーザーを使用する@ yegor256によって与えられた回答のタイトルと説明に対処しています。この回答では、debian/ubuntu以外のユースケースでこれを実現する方法について説明しています。これは、ボリュームの問題に対処していません。

FedoraやCentOSなどのRed Hatベースのシステムでは、次の方法でこれを実行できます。

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

0
gbraad