目次

Rootless Docker と Podman 入門:root 権限なしでコンテナを実行

セキュリティのベストプラクティスで検証したとおり、Docker を使える人はホストのルートディレクトリをコンテナにマウントして、あらゆるファイルを読み書きできます。つまり、ホストの root 権限を持つのと同じです。Docker Engine(dockerd)自体が root で実行され、コンテナ内の root もホストの root にあたるためです(各種の隔離機能による制限はあります)。

ここでは、root を必要としない2つの方法を紹介します。Docker の Rootless モードと、もう1つのコンテナツールである Podman です。

Rootless Docker:Docker Engine を一般ユーザーで実行

Rootless モードでは dockerd とすべてのコンテナを一般ユーザーとして実行します。Linux の user namespace を使うため、コンテナ内では root(uid 0)に見えても、ホスト上ではあなたのアカウントまたは特権を持たない uid の範囲に対応します。

この節では公式の docker:29.9-dind-rootless イメージを使って検証します。ホストの設定には影響しません。

$ docker run -d --name rl --privileged docker:29.9-dind-rootless
93e609c8808360d7e63bdc214ab2ff0e76af520fb0fb9dec5b5852d57a4881fe

$ docker logs rl 2>&1 | tail -n 5
time="2026-10-13T05:22:59.775914576Z" level=info msg="Initializing buildkit"
time="2026-10-13T05:22:59.918099929Z" level=info msg="Completed buildkit initialization"
time="2026-10-13T05:22:59.929895038Z" level=info msg="Daemon has completed initialization"
time="2026-10-13T05:22:59.930093633Z" level=info msg="API listen on /run/user/1000/docker.sock"
time="2026-10-13T05:22:59.930231753Z" level=info msg="API listen on [::]:2376"

$ docker exec rl id
uid=1000(rootless) gid=1000(rootless) groups=1000(rootless)

ログによると、Docker Engine がリッスンしているのは /run/user/1000/docker.sock(ユーザー 1000 専用のパス)で、通常の /var/run/docker.sock ではありません。dockerd を実行しているユーザーは rootless(uid 1000)であり、root ではありません。

コンテナ内の root は誰か

docker コマンドが Rootless の socket(DOCKER_HOST)に接続するよう設定し、コンテナを実行します。

$ docker exec -e DOCKER_HOST=unix:///run/user/1000/docker.sock rl docker info --format '{{json .SecurityOptions}}'
["name=seccomp,profile=builtin","name=rootless"]

$ docker exec -e DOCKER_HOST=unix:///run/user/1000/docker.sock rl docker run -d --name sleeper alpine:3.23 sleep 300
18986d442e9b9282178d96e7187534b9ac19a83dd42e3b4671a5243b55bcf1ff

$ docker exec -e DOCKER_HOST=unix:///run/user/1000/docker.sock rl docker exec sleeper id
uid=0(root) gid=0(root) groups=0(root),0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)

$ docker exec rl ps -o user,pid,args | grep 'sleep 300' | grep -v grep
rootless   382 sleep 300
  • docker info のセキュリティオプションに name=rootless が追加されています。
  • コンテナ内の id は uid=0(root) を示します。コンテナ内のプログラムから見ると、これは root です。
  • ホスト(外側)から同じ sleep 300 プロセスを見ると、所有者は**一般ユーザーの rootless**です。

検証:ホストのルートディレクトリをマウントしても /etc/shadow は読めない

/etc/shadow にはパスワードのハッシュが保存され、root だけが読み取れます。通常の Docker と Rootless Docker でホストの / をマウントして読み取ります。

$ docker run --rm -v /:/host alpine:3.23 sh -c "id -u; head -n 1 /host/etc/shadow"
0
root:*::0:::::

$ docker exec -e DOCKER_HOST=unix:///run/user/1000/docker.sock rl docker run --rm -v /:/host alpine:3.23 sh -c 'id -u; head -n 1 /host/etc/shadow'
0
head: /host/etc/shadow: Permission denied
  • 通常の Docker:コンテナ内の root はホストの /etc/shadow をそのまま読み取れました。
  • Rootless Docker:コンテナ内は同じく root(id -u は 0)ですが、読み取り時に Permission denied になります。ホスト上では一般ユーザーにすぎず、Docker を起動したアカウント以上の権限を持たないためです。

そのため、コンテナが侵害された場合や、誰かが誤って -v /:/host を使った場合でも、影響範囲はそのユーザーアカウントに限られます。

Linux で Rootless Docker をインストールする

以下の手順は Docker 公式ドキュメントをもとにしています。このチュートリアルではホストに実際にインストールしていません(インストールによってホストのシステム設定が変更されます)。実際に操作するときは公式ドキュメントを参照してください。

# 1. 必要なパッケージをインストール(Ubuntu / Debian)
sudo apt-get install -y uidmap dbus-user-session

# 2. 通常の Docker がすでにインストールされている場合は無効化(推奨)
sudo systemctl disable --now docker.service docker.socket

# 3. 一般ユーザーとしてインストールスクリプトを実行(Docker Engine パッケージとともにインストール済み)
dockerd-rootless-setuptool.sh install

# 4. docker コマンドを Rootless の socket に接続(~/.bashrc に追加)
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock

# 5. 起動時に開始(ユーザーのログアウト後も実行を継続)
systemctl --user enable docker
sudo loginctl enable-linger $(whoami)

Rootless の制限

制限説明と対処法
1024 未満のポート一般ユーザーはデフォルトで 80、443 にバインドできず、-p 80:80 は失敗します。8080 などのポートを使ってリバースプロキシで転送するか、システム設定 net.ipv4.ip_unprivileged_port_start を変更します
リソース制限--memory、--cpus を使うには、ホストで cgroup v2 が必要です。また、systemd がユーザーに権限を委譲している必要があります
ネットワーク性能ユーザー空間のネットワークコンポーネントを介して転送するため、スループットは通常モードより低くなります
データの保存場所イメージと Volume はユーザーのホームディレクトリ(~/.local/share/docker)に保存され、通常モードのデータとは共有されません
一部の機能たとえば AppArmor の設定や、一部のストレージおよびネットワークドライバーはサポートされません

このチュートリアルのテスト環境では ip_unprivileged_port_start を変更してあるため、-p 80:80 はエラーにならず、上の最初の項目はここでは再現できません。

Podman:常駐プロセス不要のコンテナツール

Podman は Red Hat が主導するオープンソースのコンテナツールです。Fedora、RHEL などのディストリビューションでは、デフォルトのコンテナツールです。Docker との大きな違いは次のとおりです。

  • 常駐プロセス(daemonless)がない:Docker のコマンドは dockerd を介して実行されます。Podman のコマンドはコンテナを直接作成し、そのコンテナは実行したプロセスの子プロセスになります。
  • デフォルトで rootless:一般ユーザーが podman を実行すると、rootless モードになります。
  • コマンドは Docker とほぼ同じ:run、build、ps、images、exec、logs などのオプションは同じです。

実際に試す:Docker と同じ方法で Podman を使う

quay.io/podman/stable イメージ内で実行します(テストホストの cgroup v1 により Podman が非推奨の警告を表示するため、PODMAN_IGNORE_CGROUPSV1_WARNING=1 を指定して抑制します)。

$ docker exec -e PODMAN_IGNORE_CGROUPSV1_WARNING=1 podman podman --version
podman version 5.8.7

$ docker exec -e PODMAN_IGNORE_CGROUPSV1_WARNING=1 podman podman run --rm docker.io/library/alpine:3.23 echo hello from podman
hello from podman

$ docker exec -e PODMAN_IGNORE_CGROUPSV1_WARNING=1 podman podman run --rm alpine:3.23 echo hi
hi

$ docker exec -e PODMAN_IGNORE_CGROUPSV1_WARNING=1 podman podman build -q -t express-app /tmp/express-app
npm notice
npm notice New major version of npm available! 11.19.0 -> 12.2.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.2.0
npm notice To update run: npm install -g npm@12.2.0
npm notice
npm warn using --force Recommended protections disabled.
a5a0b2b95ea756ad73b92ead62ece1770fdb26033c69749933fe03e3988dcb8d

$ docker exec -e PODMAN_IGNORE_CGROUPSV1_WARNING=1 podman podman run -d --name app -p 3000:3000 express-app
74aeae727d68aacae32aee45d0705881fbea9b449ac1a5ee07c365b1490f42b3

$ docker exec -e PODMAN_IGNORE_CGROUPSV1_WARNING=1 podman podman exec app wget -qO- localhost:3000
{"message":"Hello from Express","node":"v24.21.0"}

$ docker exec -e PODMAN_IGNORE_CGROUPSV1_WARNING=1 podman su podman -c 'podman run --rm docker.io/library/alpine:3.23 id -u; podman info --format {{.Host.Security.Rootless}}'
0
true
  • podman run の使い方は Docker と同じで、--rm、-d、-p などのオプションをそのまま使えます。
  • podman build はNode.js アプリの Dockerfile をそのまま使い、変更なしでビルドできます。コンテナも正常に応答します。
  • イメージ名は docker.io/library/alpine:3.23 のように完全な形式で書くことをおすすめします。Podman の短縮名(alpine:3.23)では、どの Registry からダウンロードするかがシステム設定で決まります。ディストリビューションによって設定が異なる場合があります。
  • 最後に一般ユーザー podman に切り替えて実行します。podman info では rootless が true と表示されます。コンテナ内では引き続き uid 0 ですが、Rootless Docker と同様に、ホスト上の一般ユーザーに対応しています。

インストール

# Ubuntu / Debian
sudo apt-get install -y podman

# Fedora / RHEL
sudo dnf install -y podman

Windows と macOS では Podman Desktop をインストールできます。Docker Desktop と同様に、仮想マシン内で Linux を実行します。

Docker、Rootless Docker、Podman の選び方

Docker(通常)Rootless DockerPodman
常駐プロセスdockerd(root)dockerd(一般ユーザー)なし
コンテナ内 root の実際の権限ホストの root(隔離による制限あり)一般ユーザー一般ユーザー(rootless の場合)
このチュートリアルのコマンドとの互換性完全に同じほぼ同じほとんど同じ
Docker Compose内蔵内蔵podman compose が外部実装を呼び出す
エコシステムツール(Portainer、Traefik など)完全にサポートほとんどをサポートsocket の追加設定が必要
適した用途一般的な開発、Docker Desktop、ほとんどのサーバー複数人で共有するサーバー、高いセキュリティ要件RHEL / Fedora 環境、常駐プロセスを使いたくない場合

ほとんどの初心者や一般的なプロジェクトでは、このチュートリアルのとおり Docker を使えば十分です。サーバーに複数のユーザーがログインする場合や、セキュリティ要件が高い場合は、Rootless Docker または Podman を検討してください。

まとめ

  • 通常の Docker では dockerd が root で実行されるため、Docker を使える人はホストの root 権限を持つのと同じです。
  • Rootless モードでは user namespace を使い、コンテナ内の root をホスト上の一般ユーザーに対応させます。実際に試したところ、ホストの /etc/shadow は読み取れませんでした。
  • Rootless の主な制限は、1024 未満のポート、cgroup v2 が必要なリソース制限、ネットワーク性能です。
  • Podman には常駐プロセスがなく、デフォルトで rootless です。コマンドは Docker とほぼ同じで、Dockerfile をそのままビルドできます。

練習問題

練習 1:通常の Docker で docker run --rm alpine:3.23 id を実行し、次に docker run --rm -u 1000:1000 alpine:3.23 id を実行してください。Rootless モードとは何が違いますか?

解答

-u 1000:1000 はコンテナ内のプロセスを uid 1000 で実行するだけです。dockerd は引き続き root であり、Docker を使える人は -u を付けずに root のコンテナを起動できます。Rootless モードでは Docker Engine 全体が一般ユーザーとして実行されるため、どのコンテナもホストの root 権限を取得できません。この 2 つは同時に使えます。

練習 2:Rootless Docker で docker run -d -p 80:80 nginx:1.30-alpine を実行すると失敗しました。解決方法を 2 つ挙げてください。

解答
  1. 1024 以上のポート(例:-p 8080:80)を使い、ホスト上のリバースプロキシまたはファイアウォールルールで 80 から 8080 に転送します。
  2. 一般ユーザーがポート 80 にバインドできるよう、システム設定を変更します:sudo sysctl net.ipv4.ip_unprivileged_port_start=80(再起動後も設定を維持するには、/etc/sysctl.conf に書き込みます)。

よくある質問

Rootless モードは遅くなりますか?

コンテナ内のプログラムの実行速度はほぼ同じです。ネットワーク(ユーザー空間での転送)と一部のファイルシステム操作は通常モードより遅くなりますが、ほとんどの Web サイトや開発用途では違いを感じません。

Docker Desktop に Rootless は必要ですか?

必要ありません。Docker Desktop は Windows と macOS で Docker Engine を仮想マシン内で実行するため、すでにコンピューターから切り離されています。Rootless は主に Linux サーバーや Linux デスクトップで使います。

docker コマンドをそのまま podman に置き換えられますか?

ほとんどの場合は可能です。podman run、podman build、podman ps のオプションはほぼ同じで、alias docker=podman を設定して使う人も多くいます。違いは、常駐デーモンがないこと、デフォルトで rootless であること、Compose や Docker socket 関連のツールには別途設定が必要なことです。

Podman で compose.yaml を使えますか?

使えます。podman compose はシステムにインストールされた Compose 実装(docker-compose または podman-compose)を呼び出して compose.yaml を処理するため、ほとんどの設定を利用できます。

更新日 2026年10月13日