目次
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 Docker | Podman | |
|---|---|---|---|
| 常駐プロセス | 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 つ挙げてください。
解答
- 1024 以上のポート(例:
-p 8080:80)を使い、ホスト上のリバースプロキシまたはファイアウォールルールで 80 から 8080 に転送します。 - 一般ユーザーがポート 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日