Dock Stay
UID / GID をマッピングする - user namespace の使い方・オプション・サンプル

UID / GID をマッピングする - user namespace

コンテナ内の UID/GID をホスト側の別 UID/GID にマッピングする Linux の機能。これにより「コンテナ内では root、ホストから見ると非 root」を実現し、bind mount のパーミッション問題の根本原因にもなる。

概念図

user namespace diagram

構文

bash
docker run --user 1000:1000 myapp
dockerd --userns-remap=default

実例

明示的に UID/GID 1000 で起動

bash
docker run --rm --user 1000:1000 alpine id

デーモンの UID リマップを使う

bash
docker run --rm --userns-remap=default alpine id

rootless Podman の UID マッピングを確認

bash
podman unshare cat /proc/self/uid_map

概要

User namespace は、コンテナ内の UID / GID をホストの別の UID / GID に対応付けるカーネル機能です。

例えばコンテナ内 UID 0(root)をホスト UID 100000 に割り当てることで、「コンテナでは root として動くが、ホストのファイルシステムから見ると一般ユーザー」という構図が作れます。

Podman のデフォルトと Docker の rootless モードはこの仕組みを使い、ホストの /etc/subuid/etc/subgid で各ユーザーに割り当てられた UID 範囲(通常 65536 個)をコンテナ用にマッピングします。

rootful Docker でも --userns-remap=default でデーモン全体を remap 化できます。

典型的な用途

  • Rootless 運用で「コンテナ内 root」の影響範囲を自分の UID に限定する
  • bind mount したホストディレクトリの所有権を合わせるために --user $(id -u):$(id -g) を指定する
  • 共有ホストで複数ユーザーがコンテナを使う際、UID を分離してファイル干渉を防ぐ
  • Kubernetes で securityContext.runAsUser を指定し、Pod 内プロセスを非 root にする
  • Dockerfile の USER 指定と組み合わせ、イメージ側でも非 root をデフォルトにする

コマンド例

# 明示的に UID/GID を指定
docker run --rm --user 1000:1000 -v $PWD:/work -w /work alpine sh

# デーモン全体を remap(daemon.json)
# {
#   "userns-remap": "default"
# }

# subuid / subgid の確認
cat /etc/subuid
# alice:100000:65536

# rootless Podman のマッピング
podman unshare cat /proc/self/uid_map
#          0       1000          1
#          1     100000      65536

# Dockerfile で非 root をデフォルトに
# RUN addgroup -S app && adduser -S app -G app
# USER app:app

ベストプラクティス

  • イメージ側で非 root ユーザーを用意し、Dockerfile の USER で指定してから push する
  • bind mount 前にホスト側ディレクトリの所有者をコンテナ UID に揃えておく(chown -R 1000:1000 ./data
  • /etc/subuid / /etc/subgid の範囲は 65536 以上を確保し、ネストした namespace でも足りるようにする
  • Kubernetes では PodSecurity restricted に合わせて runAsNonRoot: true を必ず有効にする
  • rootful と rootless を同じホストで混在させる場合、ファイル所有者が非直感的になるためドキュメント化する

注意点

  • bind mount の UID ミスマッチはもっともよくあるハマりどころ。コンテナ内 UID 1000 で書いたファイルがホスト側では UID 1000 のまま見えるとは限らない
  • --userns=host を指定すると user namespace を無効化し、コンテナ内 root がホスト root と同じになる。セキュリティ的に大きな後退
  • OverlayFS と user namespace の組み合わせは古いカーネルで制限があり、rootless では fuse-overlayfs が使われ IO が遅くなる
  • subuid 範囲が枯渇すると newuidmap failed で起動失敗する。usermod --add-subuids で拡張する
  • Kubernetes では long-lived PV の所有者が runAsUser と合わないと書き込みエラーになる(fsGroup で補正)

関連トピック