Docker コンテナの uid と gid の詳細な理解

Docker コンテナの uid と gid の詳細な理解

デフォルトでは、コンテナ内のプロセスは root ユーザー権限で実行され、この root ユーザーはホスト マシンの root ユーザーと同じユーザーです。恐ろしいことに聞こえますが、これはコンテナ内のプロセスに適切な機会が与えられると、ホスト マシン上のすべてを制御できることを意味するからです。この記事では、ユーザー名、グループ名、ユーザー ID (uid)、グループ ID (gid) がコンテナー内のプロセスとホスト システム間でどのようにマッピングされるかを理解します。これはシステムのセキュリティにとって非常に重要です。注: この記事のデモ環境は Ubuntu 16.04 です (下の画像はインターネットから引用したものです)。

まずuidとgidを理解しましょう

Linux カーネルは uid と gid を管理し、カーネルレベルのシステム コールを使用して、要求に権限を付与するかどうかを決定します。たとえば、プロセスがファイルに書き込もうとすると、カーネルは作成プロセスの uid と gid をチェックして、ファイルを変更するのに十分な権限があるかどうかを判断します。カーネルはユーザー名とグループ名ではなく、uid と gid を使用することに注意してください。

簡潔にするために、この記事の残りの部分では uid のみを例として使用します。システムは、基本的に gid を uid と同じように扱います。

多くの学生は、Docker コンテナを単に軽量の仮想マシンとして理解しています。これにより、コンテナ技術の理解の難しさが軽減されますが、多くの誤解を招く可能性もあります。実際、仮想マシン技術とは異なり、同じホスト上で実行されるすべてのコンテナは同じカーネル (ホストのカーネル) を共有します。コンテナ化によってもたらされる大きな価値は、これらすべての独立したコンテナ (実際にはプロセス) がカーネルを共有できることです。つまり、Docker ホスト上で数百または数千のコンテナが実行されている場合でも、カーネルによって制御される uid と gid のセットは 1 つだけになります。したがって、同じ uid は、ホストとコンテナ内の同じユーザーを表します (異なる場所に異なるユーザー名が表示される場合でも)。

ユーザー名を表示するための通常の Linux ツール (id などのコマンドなど) はカーネルの一部ではないため、同じ uid が異なるコンテナーで異なるユーザー名として表示される場合があることに注意してください。ただし、異なるコンテナーであっても、同じ uid に対して異なる権限を持つことはできません。

Linux ユーザー名前空間テクノロジーをすでに知っている場合は、「Linux 名前空間: ユーザー」を参照してください。これまでのところ、Docker はデフォルトでユーザー名前空間を有効にしていないことに注意してください。これは、この記事で説明されているケースでもあります。次の記事では、ユーザー名前空間を有効にするために Docker を設定する方法を紹介します。

コンテナ内のデフォルト ユーザーは root です。

関連する設定が行われていない場合、コンテナ内のプロセスはデフォルトで root ユーザー権限で開始されます。次のデモでは、ubuntu イメージを使用して sleep プログラムを実行します。

$ docker run -d --name sleepme ubuntu スリープ無限

上記のコマンドでは sudo が使用されていないことに注意してください。ホスト マシン上の著者のログイン ユーザーは nick で、uid は 1000 です。

ホスト内のスリープ プロセスの情報を表示します。

$ ps aux | grep スリープ

スリープ プロセスの有効なユーザー名は root です。つまり、スリープ プロセスには root 権限があります。

次にコンテナに入り、状況が以前と同じであることを確認します。スリープ プロセスにもルート権限があります。

では、コンテナ内の root ユーザーはホスト上の root ユーザーと同じですか?

答えは「はい、同じ UID に対応します」です。理由は前に説明しました。システム全体が同じカーネルを共有し、カーネルは uid と gid のセットを 1 つだけ管理します。

実際、上記の結論はデータ量を通じて簡単に検証できます。ホスト マシン上に、root ユーザーだけが読み書きできるファイルを作成します。

次に、それをコンテナにマウントします。

$ docker run --rm -it -w=/testv -v $(pwd)/testv:/testv ubuntu

コンテナ内でファイルを読み書きできます。

コンテナ内のプロセスのユーザー ID は、Dockerfile の USER コマンドまたは docker run コマンドの --user パラメータを使用して指定できます。これら 2 つの状況を別々に検討してみましょう。

Dockerfile でユーザー ID を指定する

Dockerfile にユーザー appuser を追加し、USER コマンドを使用して、プログラムをこのユーザーとして実行するように指定できます。Dockerfile の内容は次のとおりです。

Ubuntuから
useradd -r -u 1000 -g appuserを実行します
ユーザー appuser
ENTRYPOINT ["sleep", "infinity"]

test という名前のイメージにコンパイルします。

docker build -t テストを実行します。 

テストイメージを使用してコンテナを起動します。

$ docker run -d --name sleepme テスト

ホスト内のスリープ プロセスの情報を表示します。

今回表示される有効なユーザーは nick です。これは、ホスト マシンで、uid 1000 を持つユーザーの名前が nick であるためです。次にコンテナに入り、確認してみましょう。

$ docker exec -it sleepme bash 

コンテナ内の現在のユーザーは、設定した appuser です。コンテナ内の /etc/passwd ファイルを確認すると、appuser の uid が 1000 であることがわかります。これは、ホスト マシンのユーザー nick の uid と同じです。

ユーザー nick だけが読み書きできる別のファイルを作成しましょう。

また、それをデータ ボリュームとしてコンテナーにマウントします。

$ docker run -d --name sleepme -w=/testv -v $(pwd)/testv:/testv テスト

コンテナでは、testfile の所有者は appuser になり、もちろん appuser にはファイルの読み取りと書き込みの権限があります。

ここで一体何が起こったのでしょうか?これは何を示しているのでしょうか?

まず、ホスト システムには、uid 1000 のユーザー ニックネームが存在します。次に、コンテナ内のプログラムは appuser として実行されます。これは、Dockerfile プログラムで USER appuser コマンドを使用して指定されます。

実際、システム カーネルによって管理される uid 1000 は 1 つだけです。ホスト マシンではユーザー nick と見なされ、コンテナーではユーザー appuser と見なされます。
したがって、明確にしておく必要があることが 1 つあります。コンテナー内では、ユーザー appuser はコンテナー外のユーザー nick の権利と権限を取得できるということです。ホスト上のユーザー nick または uid 1000 に付与された権限は、コンテナー内の appuser にも付与されます。

コマンドライン引数からユーザーIDをカスタマイズする

docker run コマンドの --user パラメータを使用して、コンテナ内のプロセスのユーザー ID を指定することもできます。たとえば、次のコマンドを実行します。

$ docker run -d --user 1000 --name sleepme ubuntu スリープ無限

コマンドラインでパラメータ --user 1000 を指定したので、スリープ プロセスの実効ユーザーは nick として表示されます。コンテナに入って見てみましょう:

$ docker exec -it sleepme bash 

何が起こっているのか?ユーザー名が「名前がありません!」と表示される! /etc/passwd ファイルを確認すると、確かに uid 1000 のユーザーは存在しません。ユーザー名がなくても、ユーザー ID の権限にはまったく影響しません。ニックネームを持つユーザーだけが読み書きできるファイルの読み書きは引き続き可能で、ユーザー情報はユーザー名ではなく uid に置き換えられます。

コンテナの作成時に docker run --user で指定されたユーザー ID は、Dockerfile で指定された値を上書きすることに注意してください。
テスト イメージを使用して 2 つのコンテナを再度実行します。

$ docker run -d テスト

スリープ プロセス情報を表示します。

$ docker run --user 0 -d テスト

スリープ プロセス情報を再度確認します。

--urser 0 パラメータを指定するプロセスは、有効なユーザーが root であることを示しており、コマンドラインパラメータ --user 0 が Dockerfile 内の USER コマンドの設定をオーバーライドすることを示しています。

要約する

この記事の例から、コンテナ内で実行されているプロセスにもホスト リソースへのアクセス権があることがわかります (Docker はデフォルトでユーザーを分離しません)。もちろん、一般的にコンテナ テクノロジでは、コンテナ内のプロセスの可視リソースがコンテナ内でブロックされます。ただし、データ ボリューム内のファイルに対する操作で示したように、コンテナー内のプロセスがホスト マシンのリソースにアクセスする機会を得ると、その権限はホスト マシン上のユーザーの権限と同じになることがわかります。したがって、より安全な方法は、デフォルトのルート ユーザーを使用するのではなく、コンテナー内のプロセスに適切な権限を持つユーザーを指定することです。もちろん、Linux のユーザー名前空間テクノロジーを使用してユーザーを分離するという、より良い解決策があります。次の記事では、ユーザー名前空間のサポートを有効にするために Docker を構成する方法を紹介します。

参照:

Docker コンテナでの uid と gid の動作を理解する
Docker エンジンのユーザー名前空間の紹介
ユーザー名前空間でコンテナを分離する

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

<<:  MySQLの日付文字列タイムスタンプ変換の詳細な説明

>>:  redhat7 に yum 経由で mysql5.7.17 をインストールするチュートリアル

推薦する

Vue はグラフィック検証コードログインを実装します

この記事では、グラフィック認証コードログインを実装するためのVueの具体的なコードを参考までに紹介し...

MySQL インデックスの原理と使用例の分析

この記事では、例を使用して MySQL インデックスの原理と使用方法を説明します。ご参考までに、詳細...

MySQL データベースで機密データの暗号化と復号化を実装する方法

目次1. 準備2. MySQL暗号化関数方式2.1 MySQL 暗号化2.2 MYSQL 復号化3....

div要素に丸い境界線を追加する方法

以下のように表示されます。 CSSコードコンテンツをクリップボードにコピー分割{境界線: 2px 固...

MySQL におけるさまざまな一般的な結合テーブルクエリの例の概要

この記事では、例を使用して、MySQL のさまざまな一般的な結合テーブルクエリについて説明します。ご...

見栄えの良い CSS カスタム スタイル (タイトル h1 h2 h3)

レンダリングBlog Gardenでよく使われるスタイル /*タイトル h1 h2 h3 スタイル*...

js の hasOwnProperty のプロパティとインスタンスの使用法の詳細な説明

1. js は hasOwnProperty が不正に占有されることから保護しません。オブジェクトに...

MySQL 8.0.15 winx64 のインストールと設定方法のグラフィックチュートリアル (Windows の場合)

この記事では、MySQL 8.0.15 winx64のインストールと設定方法を参考までに紹介します。...

Linux(中心OS7)は、Java Webプロジェクトの実行環境を構築するためにJDK、Tomcat、MySQLをインストールします。

1. JDKをインストールする1. 古いバージョンまたはシステム独自のJDKをアンインストールする...

ピクセルを包括的なブランド体験に変えるヒント

編集者:この記事では、インタラクティブデザインがブランドコミュニケーションチェーン全体で果たすべき役...

JSはクリックドロップ効果を実装します

jsはクリックとドロップの特殊効果を実現します。まずは効果画像を見てみましょうさっそく始めましょう。...

HTML タグのリストと使用方法

HTMLタグのリストマークタイプ名前または意味効果述べるファイルのタグ付け<HTML> ...

CSS を使用してマウスをホバーすることで他のタグのスタイルを変更するサンプルコード

序文:私の知る限り、現在 CSS で制御できるのは、タグをホバーしたときにそのタグの下の兄弟タグとサ...

CSSの固定位置属性の詳細な説明

モバイル アプリを開発する場合、Web サイトが特定の高さまでスクロールしたときにコンテンツの一部を...

フロートとBFCをクリアするCSSメソッド

イギリスBFC: ブロック書式設定コンテキストBFCレイアウトルール内箱は縦方向に次々に配置されます...