web-dev-qa-db-ja.com

Dockerでのユーザーファイルの所有権について:リンクされたボリュームのアクセス許可の変更を回避する方法

次の些細なDockerfileを検討してください。

FROM debian:testing
RUN  adduser --disabled-password --gecos '' docker
RUN  adduser --disabled-password --gecos '' bob 

他に何もない作業ディレクトリ内。 Dockerイメージをビルドします。

docker build -t test .

次に、コンテナでbashスクリプトを実行し、作業ディレクトリをbobのホームディレクトリの新しいサブディレクトリにリンクします。

docker run --rm -it -v $(pwd):/home/bob/subdir test 

コンテナのsubdirのコンテンツの所有者は誰ですか?コンテナで、次を実行します。

cd /home/bob/subdir
ls -l

表示される広告:

-rw-rw-r-- 1 docker docker 120 Oct 22 03:47 Dockerfile

聖なる煙! dockerはコンテンツを所有しています!コンテナの外側のホストマシンに戻ると、元のユーザーがまだDockerfileを所有していることがわかります。 bobのホームディレクトリの所有権を試してみましょう。コンテナで、次を実行します。

chown -R bob:bob /home/bob
ls -l 

そして私達は見る:

-rw-rw-r-- 1 bob bob 120 Oct 22 03:47 Dockerfile

ちょっと待って!コンテナの外側で、ls -lを実行します

-rw-rw-r-- 1 1001 1001 120 Oct 21 20:47 Dockerfile

独自のファイルを所有しなくなりました。ひどいニュースです!


上記の例でユーザーを1人だけ追加した場合、すべてがよりスムーズに行われます。何らかの理由で、Dockerはfirstの非ルートユーザーが所有するホームディレクトリを作成しているようです(以前のユーザーで宣言されている場合でも)画像)。同様に、このfirstユーザーは、私のホームユーザーと同じ所有権に対応しています。

質問1それは正しいですか?誰かが私にこれのドキュメントを教えてくれますか、私は上記の実験に基づいて推測しています.

質問2:おそらく、これらは両方ともカーネル上で同じ数値を持っているためであり、ホームユーザーがid 1000ではないシステムでテストした場合、アクセス許可が変更される可能性がありますどんな場合でも?

質問:本当の質問は、もちろん、「これについてどうすればいいですか?」です。 bobが特定のホストマシンでbobとしてログインしている場合、彼はコンテナをbobとして実行でき、ホストアカウントでファイルのアクセス許可を変更できません。現状では、アカウントを変更しないように、ユーザーdockerとしてコンテナーを実行する必要があります。

とにかく聞きましたが、どうしてそんなに奇妙なDockerfileを持っているのですか?私も時々疑問に思う。さまざまなユーザーがログインできるwebapp(RStudioサーバー)のコンテナーを作成しています。これは、有効なユーザー名としてLinuxマシンのユーザー名と資格情報を使用するだけです。これは、複数のユーザーを作成したいという異例の動機をもたらします。実行時にのみユーザーを作成することでこれを回避できますが、何も問題ありません。ただし、単一のdockerユーザーを追加したベースイメージを使用して、rootとして実行せずにインタラクティブに使用できるようにします(ベストプラクティスに従って)。これは、そのユーザーがfirstユーザーになり、すべてを所有するため、すべてが台無しになるため、他のユーザーとしてログオンしようとすると失敗します(アプリは起動できないため起動できません)書き込み権限がありません)。スタートアップスクリプトを実行するとchownが最初にこの問題を解決しますが、リンクされたボリュームのアクセス許可を変更するコストがかかります(ボリュームをリンクしている場合は明らかに問題になります)。

63
cboettig

あれは正しいですか?誰かが私にこれのドキュメントを教えてくれますか、私は上記の実験に基づいて推測しています.

おそらく、これは両方ともカーネルで同じ数値を持っているからであり、ホームユーザーがid 1000ではないシステムでテストした場合、すべての場合にアクセス許可が変更されますか?

info coreutils 'chown invocation'を読んでください。これにより、ファイルのパーミッション/所有権がどのように機能するかをよりよく理解できるかもしれません。

ただし、基本的に、マシン上の各ファイルには、アクセス許可と所有権を定義するビットセットが付けられています。ファイルをchownすると、これらのビットを設定するだけです。

ユーザー名またはグループ名を使用して特定のユーザー/グループにchownすると、chown/etc/passwdでユーザー名を探し、/etc/groupでグループを探します名前をIDにマップします。これらのファイルにユーザー名/グループ名が存在しない場合、chownは失敗します。

root@dc3070f25a13:/test# touch test
root@dc3070f25a13:/test# ll
total 8
drwxr-xr-x  2 root root 4096 Oct 22 18:15 ./
drwxr-xr-x 22 root root 4096 Oct 22 18:15 ../
-rw-r--r--  1 root root    0 Oct 22 18:15 test
root@dc3070f25a13:/test# chown test:test test
chown: invalid user: 'test:test'

ただし、マシン上にこれらのIDを持つユーザー/グループが存在するかどうかに関係なく、IDを使用して(もちろん、いくつかの正の整数範囲内で)chownファイルを作成できます。

root@dc3070f25a13:/test# chown 5000:5000 test
root@dc3070f25a13:/test# ll
total 8
drwxr-xr-x  2 root root 4096 Oct 22 18:15 ./
drwxr-xr-x 22 root root 4096 Oct 22 18:15 ../
-rw-r--r--  1 5000 5000    0 Oct 22 18:15 test

UIDおよびGIDビットはファイル自体に設定されるため、これらのファイルをdockerコンテナー内にマウントすると、ファイルはホスト上と同じ所有者/グループUIDを持ちますが、今では/etc/passwdにマッピングされますコンテナ。ルート(UID 0)が所有していない限り、おそらく別のユーザーになります。

本当の質問は、もちろん、「これについてどうすればいいですか?」です。 bobが特定のホストマシンにbobとしてログインしている場合、彼はコンテナーをbobとして実行でき、ホストアカウントでファイルのアクセス許可を変更することはできません。現状では、アカウントが変更されないようにするために、実際にはコンテナーをユーザーDockerとして実行する必要があります。

現在の設定では、UID>ホストの/etc/passwdのユーザー名がUID>コンテナーのユーザー名/etc/passwdと一致することを確認する必要があるようです。ホストにログインしているのと同じユーザーとして、マウントされたユーザーディレクトリと対話します。

useradd -u xxxxを使用して、特定のユーザーIDを持つユーザーを作成できます。 Buuuut、それは面倒な解決策のようです...

ホストユーザーのホームディレクトリをマウントしないソリューションを考え出す必要があるかもしれません。

25
Chris McKinnel

私が見つけた2つのオプション:

すべてのことを行います(仕事をした後)

docker run -v `pwd`/shared:/shared imageを実行しましたが、コンテナーはpwd/shared内にファイルを作成しました。これはdockerプロセスが所有する方法です。ただし、/sharedはまだ私が所有しています。 Dockerプロセス内で、

chown -R `stat -c "%u:%g" /shared` /shared

stat -c "%u:%g" /sharedは、私の場合は1000:1000を返します。これはユーザーのuid:gidです。 docker conatainer内にユーザー1000がいなくても、idはそこにあります(ユーザー名を尋ねるとstat /sharedは単に「不明」と言います)。

とにかく、chown/sharedの内容の所有権を1000:1000に素直に転送します(これは、それが存在する限り、存在しませんが、コンテナーの外では私です)。だから私は今すべてのファイルを所有しています。コンテナは、必要に応じて物事を変更できます。これは、コンテナの観点からすると、rootであるためです。

そして、すべてが世界に順調です。

docker run -uので、作成されたすべてのファイルは自動的に正しい所有者を持ちます

これを行う別の方法は、docker runの-uフラグです。

docker run -v `pwd`/shared:/shared -u `stat -c "%u:%g" /shared` ubuntu bash

この方法では、コンテナ内のdockerユーザーはyouruid:yourgidです。

ただし:これは、コンテナ内でルート権限を放棄することを意味します(apt-get installなど)。その新しいuidでユーザーを作成し、rootグループに追加しない限り。

54
Jared Forsyth

したがって、この投稿では、ルートとして実行されているDockerコンテナから出たすべてのファイル(ルートが所有する)の所有権を復元する、ホストの非特権ユーザーに探しました。

ルート内でコンテナ内のプロセスを実行する必要があったため、docker runで-uを使用できません。

私は自分がしたことを誇りに思っていませんが、bashスクリプトの最後にこれを追加しました。

docker run --rm -it \
    --entrypoint /bin/sh \
    -e Host_UID=`id -u` \
    -v ${Host_FOLDER_OWNED_BY_ROOT}:/tmp \
    Alpine:latest \
    -c 'chown -R ${Host_UID}:${Host_UID} /tmp/'

行の一部を分解してみましょう。

  • コンテナ内で/ bin/shを実行します。

--entrypoint/bin/sh

  • 現在のユーザーのuidを環境変数としてコンテナに渡します。

-e Host_UID = `id -u`

  • 再所有したいフォルダをユーザーにマウントします(rootが所有するファイルで満たされ、rootとして実行された以前のコンテナによって出力されます )、この新しいコンテナの/tmpの下:

-v $ {Host_FOLDER_OWNED_BY_ROOT}:/ tmp

  • ホストユーザーのuidを使用して、ターゲットディレクトリ(/tmpのコンテナ内にマウント)でchownを再帰的に実行します。

-c 'chown -R $ {Host_UID}:$ {Host_UID}/tmp /'

そのため、これで、rootまたはSudoに特権を「エスカレート」することなく、現在のユーザーに所有ファイルを戻しました。

汚れていますが、うまくいきました。お役に立てば幸いです。

2
BBerastegui