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 をインストールするチュートリアル

推薦する

HTML の div、td、p およびその他のコンテナーでの強制改行と非改行の実装

1. 改行を強制せず、省略記号で終了します。コードをコピーコードは次のとおりです。 <div ...

VmWareでcentos7をインストールするときにインターネットにアクセスできない問題の解決策

Centos7 のインストール時に VmWare がインターネットにアクセスできない場合はどうすれば...

MySQL実行計画の詳細な説明

EXPLAIN ステートメントは、MySQL がステートメントを実行する方法に関する情報を提供します...

Webフロントエンド開発におけるエラーを見つけるための基本的な考え方

WEB開発は主に2つのインタラクション(B/Sデータ)から構成されますブラウザ: 1html、css...

背景画像にテキストを表示するためのCSS

効果: <div class="imgs"> <!-- 背景画...

セマンティックウェブページ XHTML セマンティックマークアップ

構造とプレゼンテーションを分離するもう 1 つの重要な側面は、セマンティック マークアップを使用して...

Linux でのマルチスレッドにおけるフォークの紹介

目次質問:ケース(1)子スレッドを作成する前にフォークするケース(2)子スレッドを作成した後にフォー...

Linux プロセス管理ツール スーパーバイザーのインストールと設定のチュートリアル

環境: CentOS 7公式ドキュメント: http://supervisord.org/インストー...

仮想マシンの複製に関するVirtual Boxチュートリアル図

VMに慣れた後、BOXに切り替えるのは少し異なります。たとえば、コピーネットワークカードを2枚使って...

ウェブページの幅を携帯電話の画面(ビューポート)の幅に自動的に適応させる実装コード

一般的な書き方は次のとおりです。 XML/HTML コードコンテンツをクリップボードにコピー<...

CSS3で蓮の花が咲くアニメーション効果を実現

まずは効果を見てみましょう:この効果は非常に華やかに見えますが、原理は複雑ではありません。1 枚の花...

WeChatアプレットがテキストスクロールを実装

この記事の例では、WeChatアプレットでテキストスクロールを実装するための具体的なコードを参考まで...

MySQL 8.0.12 の詳細なインストールおよびアンインストール チュートリアル

1. MySQL 8.0.12 バージョンのインストール手順。 1. ダウンロードhttps://d...

CSS3 FlexBox の伸縮自在なレイアウトを 10 分で理解する

基本的な紹介特徴Flexbox は、よりシンプルで効率的なレイアウト方法を提供する CSS 表示タイ...