2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Podman rootless:「UID/GID」、 `podman unshare`、`:U`、`subuid`

2
Last updated at Posted at 2026-06-14

Rootless Podmanを使っていると、ホスト側でファイルを見たときに、次のような所有者になっていることがあります。

100999 100999

/etc/passwd を見ても、そんなユーザーはいない。

その結果、ホスト側の通常ユーザーでファイルを削除しようとして、

rm: Permission denied

のようなエラーになることがあります。

これは、Rootless Podmanで使われる ユーザー名前空間 と UID/GIDマッピング が関係しています。


ユーザー名前空間とは

一言でいうと、ユーザー名前空間とは、

UID/GIDの見え方を変えるLinuxの仕組み

です。

Linuxでは、ユーザーやグループは名前ではなく、内部的にはUID/GIDという数値で管理されています。

例えば、通常は次のように扱われます。

UID 0    = root
UID 1000 = 一般ユーザー

コンテナ内でもUID/GIDは使われます。

ただし、ユーザー名前空間を使うと、

コンテナ内で見えているUID/GID

と、

ホスト側で実際に使われているUID/GID

を別の値にマッピングできます。


コンテナ内のrootは、ホストのrootとは限らない

ユーザー名前空間を使うと、コンテナ内ではrootに見えていても、ホスト側では本物のrootではない、という状態を作れます。

つまり、

コンテナ内のroot ≠ ホストのroot

にできます。

これが重要です。

コンテナ内でrootとして動いているプロセスがあっても、それがホストOS全体を自由に操作できるrootとは限りません。

Rootless Podmanでは、この仕組みによって、一般ユーザーでも比較的安全にコンテナを実行できるようになっています。


Rootless PodmanでのUID/GIDマッピング

Rootless Podmanでは、基本的にユーザー名前空間が使われます。

標準的なrootless環境では、ざっくりいうと次のような対応になります。

コンテナ内 UID 0
  → ホスト側ではPodmanを実行した一般ユーザーのUID

コンテナ内 UID 1以降
  → ホスト側では /etc/subuid に割り当てられた範囲

例えば、ホスト側のユーザー user02 のUIDが 1000 だとします。

さらに、/etc/subuid に次のような設定があるとします。

user02:100000:65536

この場合、Podmanはコンテナ内のUIDを、ホスト側のUIDに次のように対応させることがあります。

コンテナ内 UID 0    → ホスト UID 1000
コンテナ内 UID 1    → ホスト UID 100000
コンテナ内 UID 2    → ホスト UID 100001
...
コンテナ内 UID 1000 → ホスト UID 100999

つまり、コンテナ内では UID 1000 のユーザーが作ったファイルでも、ホスト側から見ると UID 100999 が所有しているように見えることがあります。


なぜホスト側で「謎のUID」に見えるのか

ホスト側で次のように確認したとします。

ls -ln

すると、次のように表示されることがあります。

-rw-r--r-- 1 100999 100999 1234 Jun 14 file.txt

これは、ホストの /etc/passwd に 100999 というUIDのユーザーがいる、という意味ではありません。

実際には、

コンテナ内のUID 1000

が、

ホスト側のUID 100999

にマッピングされて見えている状態です。

そのため、ホスト側から見ると、

知らないUIDが所有しているファイル

のように見えます。


ホスト側で削除できないことがある

このようなファイルは、ホスト側の通常ユーザーから見ると、自分の所有物ではないように見えることがあります。

そのため、次のように削除しようとしても、

rm -rf ./data

次のようなエラーになることがあります。

rm: cannot remove './data/file.txt': Permission denied

これは、Rootless Podmanでvolumeやbind mountを使っているときによく遭遇する現象です。


そこで podman unshare

このようなときに使えるのが podman unshare です。

例えば、次のように実行します。

podman unshare rm -rf ./data

podman unshare は、Podman rootless用のユーザー名前空間に入ってコマンドを実行するためのコマンドです。

  • podman unshareで実行したコマンドは、Podmanのuser namespace内ではroot、つまりUID 0として実行される。それはホストのrootではない
  • 特定のコンテナ内に入って実行するわけではない。

通常のホスト側から見ると、

所有者: 100999

のように見えていたファイルでも、Podmanのユーザー名前空間の中から見ると、

これはコンテナ内のUID 1000に対応するファイル

のように、Podmanのマッピングに従った見え方になります。

その結果、ホスト側からは削除できなかったファイルでも、podman unshare の中では削除できる場合があります。


UID/GIDマッピングを確認する

現在のRootless Podmanで、どのようにUID/GIDがマッピングされているかは、次のように確認できます。

podman unshare cat /proc/self/uid_map
podman unshare cat /proc/self/gid_map
出力の書式
container_id   host_id   size
  • container_id: 名前空間の中で見える UID/GID の開始番号
  • host_id: ホスト側の実 UID/GID の開始番号
  • size: 連続して対応づけられる個数

出力例は環境によって異なりますが、例えば次のような形になります。

         0       1000          1
         1     100000      65536

これは、ざっくりいうと次の意味です。

名前空間内 UID 0      → ホスト UID 1000
名前空間内 UID 1以降  → ホスト UID 100000以降

つまり、Rootless Podmanの中ではrootに見えていても、ホスト側では通常ユーザーやsubuid範囲にマッピングされている、ということです。


subuid とは

subuid は subordinate UID の略です。

直訳すると「従属UID」や「補助UID」のような意味になります。

Rootless Podmanの文脈では、次のように考えると分かりやすいです。

subuid = 一般ユーザーに割り当てられた、コンテナ用の追加UID範囲

設定は /etc/subuid に書かれています。

例えば、次のような行があるとします。

user02:100000:65536

これは、

ユーザー user02 は、
ホスト上の UID 100000 から 65536個分を、
ユーザー名前空間内で使ってよい

という意味です。

範囲でいうと、次のようになります。

100000 ~ 165535

同じように、GID版が /etc/subgid です。

/etc/subuid = 追加で使えるUID範囲
/etc/subgid = 追加で使えるGID範囲

確認するには、次のようにします。

cat /etc/subuid
cat /etc/subgid

Rootless Podmanは、この /etc/subuid と /etc/subgid の範囲を使って、コンテナ内のUID/GIDをホスト側のUID/GIDに対応させます。


subuid があるから謎のUIDに見える

例えば、/etc/subuid が次の内容だったとします。

user02:100000:65536

このとき、コンテナ内のUID 1000がホスト側ではUID 100999として見えることがあります。

コンテナ内 UID 1000
  → ホスト側 UID 100999

そのため、ホスト側で ls -ln すると、

100999 100999 file.txt

のように表示されることがあります。

これは、ホストに 100999 というユーザーが存在するという意味ではありません。

コンテナ内のUIDが、ホスト側のsubuid範囲に変換されて見えているだけです。


volumeの :U オプション

podman unshare は、すでに作られてしまったファイルやディレクトリを後から操作したいときに便利です。

一方で、コンテナにディレクトリをマウントするときに、最初から所有者を調整する方法もあります。

それが、volumeオプションの :U です。

例えば、次のように使います。

podman run --rm \
  -v ./data:/data:U \
  イメージ名

この例は、ホスト側の ./data をコンテナ内の /data にマウントしています。

厳密には、これはホスト上のディレクトリをコンテナに見せる bind mount です。

ただし、-v で指定するマウント全般を、ざっくり「volumeマウント」と呼ぶこともあります。


:U は何をするのか

:U を付けると、Podmanはマウント元のファイルやディレクトリに対して、所有者とグループを調整します。

簡単にいうと、

コンテナ内のユーザーが書き込めるように、
ホスト側の所有者を変更してからマウントする

という動きです。

例えば、コンテナ内のアプリケーションが /data に書き込みたいとします。

しかし、ホスト側の ./data の所有者が、コンテナ内のユーザーに対応していない場合、コンテナ内で次のようなエラーになることがあります。

Permission denied

このような場合に、

podman run --rm \
  -v ./data:/data:U \
  イメージ名

とすると、Podmanが所有者を調整してくれるため、コンテナ内から書き込めるようになる場合があります。


SELinux環境では :Z と組み合わせることもある

RHEL系、Fedora、AlmaLinux、Rocky Linuxなど、SELinuxが有効な環境では、UID/GIDだけでなくSELinuxラベルが原因で書き込めないこともあります。

その場合は、:Z と :U を組み合わせることがあります。

podman run --rm \
  -v ./data:/data:Z,U \
  イメージ名

:Z はSELinuxラベルをコンテナ用に調整します。

:U はUID/GIDの所有者を調整します。

つまり、

:Z = SELinuxラベルの調整
:U = UID/GID所有者の調整

です。

SELinuxが有効な環境では、所有者が合っていてもラベルが合っていないと書き込めないことがあるため、両方が関係する場合があります。


:U の注意点

:U は便利ですが、かなり強い操作です。

理由は、:U がホスト側のファイルやディレクトリに対して、実際に chown を行うからです。

しかも、対象ディレクトリ配下に対して再帰的に所有者変更が行われます。

そのため、次のようなディレクトリには安易に使わない方がよいです。

ホームディレクトリ全体
重要な設定ファイルがあるディレクトリ
他のアプリケーションも使っているディレクトリ
大量のファイルがあるディレクトリ

例えば、次のような指定は危険です。

podman run --rm \
  -v $HOME:/home/user:U \
  イメージ名

ホームディレクトリ配下の所有者が変わってしまうと、ホスト側の通常ユーザーから扱いにくくなる可能性があります。

:U を使うなら、コンテナ専用に作ったディレクトリに限定するのが安全です。

mkdir ./data

podman run --rm \
  -v ./data:/data:U \
  イメージ名

podman unshare chown で手動調整する

:U を使わず、手動で所有者を調整したい場合は、podman unshare chown を使う方法もあります。

例えば、Podmanのユーザー名前空間内で、./data の所有者を変更したい場合は、次のようにします。

podman unshare chown -R 0:0 ./data

この場合の 0:0 は、ホストのrootという意味ではなく、Podmanのユーザー名前空間内での UID 0 / GID 0 です。

つまり、ホスト側から見ると別のUID/GIDに見えることがあります。

ここでも重要なのは、

podman unshare の中で見えているUID/GID

と、

ホスト側で見えているUID/GID

は同じとは限らない、ということです。


--userns=keep-id という選択肢

Rootless Podmanでは、--userns=keep-id を使う方法もあります。
(Composeならuserns_mode: keep-id)

podman run --rm \
  --userns=keep-id \
  -v ./data:/data \
  イメージ名

--userns=keep-id は、ホスト側の自分のUID/GIDを、コンテナ内でも同じUID/GIDとして使うためのオプションです。

例えば、ホスト側の自分のUIDが 1000 の場合、コンテナ内でもUID 1000 として扱いやすくなります。

これにより、bind mountしたディレクトリの権限問題を避けやすくなる場合があります。

ただし、すべてのケースで --userns=keep-id が最適とは限りません。

コンテナイメージ側が特定のUIDで動く前提になっている場合や、rootとして初期化処理を行う前提になっている場合は、別の調整が必要になることもあります。


podman unshare、:U、--userns=keep-id の使い分け

ざっくり分けると、次のようになります。

方法 用途
podman unshare rm -rf すでにできてしまったファイルやディレクトリを削除する
podman unshare chown Podmanのユーザー名前空間内の視点で所有者を手動調整する
-v ./data:/data:U マウント時に所有者を自動調整する
--userns=keep-id ホスト側の自分のUID/GIDをコンテナ内でも維持したい場合に使う
:Z SELinuxラベルをコンテナ用に調整する

例えば、すでに消せないディレクトリができている場合は、次のようにします。

podman unshare rm -rf ./data

これから新しくマウントする専用ディレクトリを作る場合は、次のように :U を使う方法があります。

mkdir ./data

podman run --rm \
  -v ./data:/data:U \
  イメージ名

ホスト側の自分のUID/GIDのまま扱いたい場合は、--userns=keep-id を検討できます。

podman run --rm \
  --userns=keep-id \
  -v ./data:/data \
  イメージ名

SELinuxが有効な環境でラベルも調整したい場合は、:Z を組み合わせます。

podman run --rm \
  -v ./data:/data:Z,U \
  イメージ名

Dockerとの違い

通常のrootful Dockerでは、Docker daemonがroot権限で動いています。

そのため、ユーザー名前空間のリマップを明示的に有効化していない限り、Rootless PodmanのようなUID/GIDのずれは起きにくいです。

一方、Rootless Podmanでは、一般ユーザーで安全にコンテナを動かすために、ユーザー名前空間が基本的に使われます。

項目 Rootless Podman 通常のrootful Docker
実行主体 一般ユーザー root権限のDocker daemon
ユーザー名前空間 基本的に使う 通常は明示設定しない限り使わない
UID/GIDのずれ 起きやすい 通常は起きにくい
謎のUIDのファイル 発生することがある userns-remap等を使うと発生することがある
消せないファイルへの対応 podman unshare が使える root所有なら sudo rm や sudo chown が必要になることがある
volume所有者の自動調整 :U が使える 同じ意味の :U は通常使わない

ただし、Dockerでも userns-remap や rootless mode を使う場合は、同じようにUID/GIDマッピングが関係します。

そのため、

DockerだからUID/GIDマッピングは関係ない

というわけではありません。

あくまで、

通常のrootful Dockerでは意識する機会が少ない
Rootless Podmanでは意識する機会が多い

という違いです。


まとめ

Rootless Podmanで、ホスト側に次のような所有者のファイルが見えることがあります。

100999 100999

これは、ホストに謎のユーザーが作られたという意味ではありません。

コンテナ内のUID/GIDが、ホスト側のsubuid/subgid範囲にマッピングされて見えているだけです。

重要なポイントは次のとおりです。

ユーザー名前空間
  = UID/GIDの見え方を変える仕組み

subuid / subgid
  = rootlessコンテナ用に一般ユーザーへ割り当てられた追加UID/GID範囲

podman unshare
  = Podmanのユーザー名前空間に入ってコマンドを実行する方法

:U
  = マウント元ディレクトリの所有者を、コンテナ側で扱いやすいように変更するオプション

:Z
  = SELinuxラベルをコンテナ用に調整するオプション

--userns=keep-id
  = ホスト側の自分のUID/GIDをコンテナ内でも維持したい場合に使うオプション

消せないファイルがすでにできている場合は、次のようにします。

podman unshare rm -rf ./data

これから新しく専用ディレクトリをマウントする場合は、次のように :U を使う方法があります。

podman run --rm \
  -v ./data:/data:U \
  イメージ名

ただし、:U はホスト側のファイルに対して実際に再帰的な chown を行います。

そのため、ホームディレクトリ全体や重要な設定ディレクトリには安易に使わず、コンテナ専用のディレクトリに限定して使うのが安全です。


参考

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?