お世話になっております。App Service サポート担当の押田です。
本記事は 2022 年 6 月 30 日に公開されました Docker User Namespace remapping issues の日本語訳です。
翻訳内容には細心の注意を払っておりますが、もし原文内容と齟齬がある場合は、原文の内容を優先くださいませ。
Docker にはユーザ名前空間と名前空間の再割り当て(userns とも呼ばれます)の概念があります。これを使用すると、コンテナ内のユーザーをホストマシン上の特権のないユーザーに再割当てできます。
Dockerfile で明示的に定義されたユーザーが、許可された ID 範囲の外の UID を持っている場合や、ファイル自体が大きな UID を持っている場合があります。これは、最終的にイメージがどのように構築されるか(ベースイメージ、サードパーティイメージなど)に依存するため、意図せずに発生する可能性があります。
許可された範囲外の UID が割当てされた場合、以下に示すようなエラーが発生する場合があります。
詳細については こちら のオフィシャルドキュメントもご参照ください。
重要事項
ユーザー名前空間の概念は、典型的な Linux の仕組みです。この記事で説明されているエラーは、App Service や Azure の問題ではありません。これは、ユーザー名前空間と再割当てをサポートし、マシン上の設定範囲外の ID を作成しようとしているマシンでも再現できます。
注意: App Service において、ID の範囲の変更はできません。非常に大きな ID の解決は、最終的にはイメージの開発者または管理者にて行う必要があります。
エラー
エラーの種類
ユーザー、グループまたはファイルが大きな UID または、GUID に再割当てされる場合、以下のようなエラーを目にする可能性があります。
failed to register layer: Error processing tar file(exit status 1): Container ID 1000000 cannot be mapped to a host IDErr: 0, Message: failed to register layer: Error processing tar file(exit status 1): Container ID 1000000 cannot be mapped to a host IDOCI runtime create failed: container_linux.go:380: starting container process caused: setup user: cannot set uid to unmapped user in user namespace: unknown
様々なパターンのメッセージがありますが、根本原因としては、uid を ユーザー名前空間に再割当てできないことに起因します。
エラーの発生箇所
App Sericeでは、イメージの pull 実行時に発生します。これらのエラーが発生した場合、pull に失敗し、サイトアクセス時に Application Error :( が表示されたり、HTTP ステータス 502 が返却されることになります。
以下は、pull 失敗時のエラー例となります。
1 | 2022-07-01T00:02:29.030Z INFO - 6f199d2c4d2f Extracting 32KB / 308KB |
これらのログは ログストリーム 機能や、Kudu にて _docker.log. で終わるファイル名のログファイルから確認することができます。
回避方法
ファイルの特定
次の操作は App Service 上ではなく、ローカル環境で実施する必要があります。
問題のあるコンテナイメージをローカル環境で実行し find / \( -uid 1000000 \) -ls 2>/dev/null を shell から実行します。
1000000 は実際に pull 失敗時のエラーメッセージに含まれる値に置き換えます。
理想的には、以下のように表示されるはずです。この場合、UID が大きすぎるユーザーが所有するファイルがあります。
1 | # find / \( -uid 1000000 \) -ls 2>/dev/null |
注意: もし、大きな
UIDがコンテナ内のUSERとして定義されている場合、全てのファイルが該当のユーザーに所有されていると表示される場合があります。
ファイルの確認
次の操作は App Service 上ではなく、ローカル環境で実施する必要があります。
特定のファイルが特定できた場合、次のコマンドを実行することで、大きな ID マッピングが実行されていることがわかります。
ls -ln file-with-high-id
サンプル実行例:
1 | ls -ln file-with-high-id |
ファイルまたはユーザーの修正
このためには、ファイルの所有権を変更する必要があります。例えばファイルに対しては Dockerfile 内で chown コマンドを利用します。
もし、以下のようにユーザーがイメージ内に定義されている場合、以下のように割り当てられるIDをセットする必要があります。
1 | RUN groupadd veryhigh -g 1000000 |
もし、イメージがサードパーティ製の場合は、UID を使用しているメンテナーに連絡してください。あるいは、サードパーティ製イメージをベースとし、問題のあるファイルあるいはユーザーを変更したイメージを作成することも可能です。
問題を解消した後に、イメージを再ビルドし、デプロイすることができます。この作業はローカルで実施する必要があります。
NPM 利用プロジェクトにおける ユーザー名前空間再割当てエラー
特定の NPM バージョンでは、node_modules インストール時に、非常に大きな ID をファイルの所有者/作成者として割り当てることがあります。これは npm 9 系において導入されました。npm コミュニティにおいてもこの問題に関連するディスカッションが以下の 3 つのスレッドで確認できます。 一読することをお勧めします。
- RFC thread ([RRFC] Clean up file ownership story)
- NPM 9 change log (Breaking Changes)
- This GitHub issue (GitHub Issue 5900)
npm 9 系を利用する以下の Dockerfile を App Service にデプロイした場合、ユーザー名前空間再割当てに関するエラーが発生します。
注意: npm 5系でも発生することもあります。
(Dockerfile):
1 | FROM node:18.9.0-alpine3.15 |
App Service で発生するエラー:
1 | ERROR - failed to register layer: Error processing tar file(exit status 1): Container ID 1516583083 cannot be mapped to a host IDErr: 0, Message: failed to register layer: Error processing tar file(exit status 1): Container ID 1516583083 cannot be mapped to a host ID |
前述のアプローチと同様に、ローカル環境で調査する必要があります。 ただし、find コマンドでは、問題を起こしている UID を特定することができません。 ID 変更が発生しているためです。(詳細については前述のスレッド内に書かれています。)
NPM と node_modules に関連する問題がわかっているため、以下のアプローチで特定します。
実際には、利用するプロジェクト内の node_modules のパスに置き換えてください。
node_modules:
1 | FILES=$(find /app/node_modules/ ! -user root) |
エラーに示される ID と一致する以下の所有者名を確認することができます。
1 | -rw-r--r-- 1 501 dialout 1490 Nov 29 17:18 /app/node_modules/cookie-signature/Readme.md |
回避策としては, chown コマンドによってディレクトリ配下のファイルの所有者を変更します。
重要: chown を実行する場合、それは npm install を実行するレイヤと必ず同じレイヤで実行する必要があります。もし 2 つの異なるレイヤで実行された場合、所有者の変更は正しく動かず、名前空間再割当てに関するエラーは解消しません。
(Do)
1 | RUN npm i -g npm@9.1.1 && \ |
(Dont)
1 | RUN npm i -g npm@9.1.1 && \ |
UID を特定できない場合はどうすると良いか?
コンテナを Pull し作成エラーとなった際に、エラーメッセージから UID が特定できない場合もあります。
常にそうなるわけではありませんが、同様のアプローチ で解決することができます。
なぜなら、 find /app/node_modules/ ! -user root を実行しているためです。例えば、ユーザーが 50x の範囲にあり、グループ dialout に含まれる node_module 関連のファイルが表示される場合があります。 ファイルシステム全体を検索すると、通常、これらはユーザー/グループとして、 root と node 以外に表示される唯一のものです。
このようなシナリオの場合、50x ユーザーと dialout グループを root (または、許容範囲内にあるUID) に変更することで問題が解消します。これは、NPM インストール実行時にユーザー切り替えが起きているためとなります。NPM に関連する当セクションの先頭に記載したスレッドのリンクを参照ください。
2023 年 02 月 15 日時点の内容となります。
本記事の内容は予告なく変更される場合がございますので予めご了承ください。
※本情報の内容(添付文書、リンク先などを含む)は、作成日時点でのものであり、予告なく変更される場合があります。