次の些細な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
が最初にこの問題を解決しますが、リンクされたボリュームのアクセス許可を変更するコストがかかります(ボリュームをリンクしている場合は明らかに問題になります)。
あれは正しいですか?誰かが私にこれのドキュメントを教えてくれますか、私は上記の実験に基づいて推測しています.
おそらく、これは両方ともカーネルで同じ数値を持っているからであり、ホームユーザーが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、それは面倒な解決策のようです...
ホストユーザーのホームディレクトリをマウントしないソリューションを考え出す必要があるかもしれません。
私が見つけた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
グループに追加しない限り。
したがって、この投稿では、ルートとして実行されている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/'
行の一部を分解してみましょう。
--entrypoint/bin/sh
-e Host_UID = `id -u`
/tmp
の下:-v $ {Host_FOLDER_OWNED_BY_ROOT}:/ tmp
/tmp
のコンテナ内にマウント)でchown
を再帰的に実行します。-c 'chown -R $ {Host_UID}:$ {Host_UID}/tmp /'
そのため、これで、rootまたはSudoに特権を「エスカレート」することなく、現在のユーザーに所有ファイルを戻しました。
汚れていますが、うまくいきました。お役に立てば幸いです。