背景
前回の投稿(↓)でも少し触れましたが、
Docker-in-Docker の2つの方法 – もばらぶエンジニアブログ
現在、マルチテナントの MCP サーバー管理サービスを作っています。その際にテナント毎に MCP サーバーの実行環境を隔離する方法を検討していて、結論としては以下の通りになりました。
- 有料ユーザー → テナント毎に専用のコンテナを用意し、その中で普通にプロセスを起動する
- 無料ユーザー → 無料ユーザー用のコンテナ(複数テナントで共有)内で Bubblewrap 経由でプロセスを起動する
今回は、Docker コンテナ内で Bubblewrap を動かす方法を説明します。(短い内容です。)
Bubblewrap とは
概要
Linux 上で動作する sandbox 環境(他から隔離された環境)作成のツール(コマンド)です。Linux 環境の中に、non-root 権限の隔離された環境を作り、その sandbox からはホスト OS や他の sandbox を見る事は出来ません。
詳しくは以下のサイトをご覧ください。
containers/bubblewrap: Low-level unprivileged sandboxing tool used by Flatpak and similar projects
内部的には
Linux の名前空間と pivot_root などを使って実現しています。
Docker コンテナで動かす方法
必要な権限
先ほど、内部的には名前空間と pivot_root などを使っていると書きましたが、そのためには権限等が必要です。通常の Linux を起動している場合には root ユーザーであれば全ての機能が使えますが、Docker コンテナではデフォルトで権限が制限されているため、それらの権限を明示的に許可する必要があります。
まず、Linux の名前空間を作るには CAP_SYS_ADMIN という capability が必要です。
また、 pivot_root システムコールは、標準では Docker コンテナ内では使う事が出来ません。
Docker Compose での権限の与え方
compose.yml は以下のように記載します。
services:
foo:
build:
context: .
cap_add: # 追加する権限を指定
- SYS_ADMIN # namespace, pivot_root のために必要
security_opt: # セキュリティ関連のオプション
# pivot_root を含め、使用可能なシステムコールを明示的に許可
# https://github.com/moby/profiles/blob/main/seccomp/default.json を元に作成した
- seccomp:seccomp.json
SYS_ADMIN は良いとして、pivot_root システムコールだけを追加で許可する方法はなさそうです。そのため、以下の JSON ファイルをダウンロードしてきて、259行目辺りに "pivot_root", と追加して、それを compose.yml から指定します。
profiles/seccomp/default.json at main · moby/profiles
seccomp が何かについては、以下のドキュメントを
seccomp(2) – Linux manual page
Docker での seccomp 関連の情報は以下のドキュメントを参照してください。
Seccomp security profiles for Docker | Docker Docs
他の環境では
今回は詳しく触れませんが、Kubernetes, ECS についても少し述べます。
k8s では Linux capabilities と seccomp どちらにも対応しています。
Configure a Security Context for a Pod or Container | Kubernetes
ECS は Linx capabilities には対応しています。
AWS::ECS::TaskDefinition KernelCapabilities – AWS CloudFormation
ただ、seccomp には対応してなさそうです。
まとめ
Docker コンテナではデフォルトで権限に制限があり、そのままではコンテナ内で bubblewrap (bwrap) を実行する事が出来ません。そのために必要な事は SYS_ADMIN capability の付与と seccomp にて pivot_root システムコールの実行を許可する必要があります。