2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Docker の Rootless を考える

2
Last updated at Posted at 2025-12-18

何も考えない場合 Docker は root 権限で動くが、そうしたければ非 root 権限( = Rootless)で動かすこともできる。

Docker の実行権限について

rootless-diagram.png

Docker のデーモンとコンテナはプロセスとして動き、それぞれが権限を持つ。

そのため Docker の話をしていて Rootless という単語が出てきたら、何が Rootless なのか(デーモンが?コンテナが?)を意識する必要がある。

以下で Docker デーモン・Docker コンテナと root 権限・非 root 権限の組み合わせを考える。

Docker デーモン Docker コンテナ 説明
root root デフォルト。何でもできて便利だが脆弱性によってホスト、コンテナともに乗っ取られるかもしれない。
root 非 root デフォルトよりマシだが、ホスト側の脆弱性によってホストを乗っ取られるかもしれない。
非 root root デフォルトよりマシだが、コンテナ側の脆弱性によってコンテナを乗っ取られるかもしれない。
非 root 非 root デフォルトに比べてホスト、コンテナともに被害は抑えられるが、ネットワークやファイル読み書きで問題が出ることがある。

権限は安全と利便性の両方を考慮して決めるのが良いと思う。

デーモン・コンテナ共にユーザー権限で間に合うのであればそうすれば良いし、5 分以内にコンテナを立ち上げないと地球が爆発してしまう事態であれば両方 root で済ませてしまってもいいかもしれない。

Rootless モードを使う

Rootless モードについて

Rootless モード(Rootless Docker ともいう)を使うと Docker デーモンを非 root 権限で動作させることができる。

Rootless モードを使うとセキュリティが向上する一方で、以下のようなデメリットも有る。

  • 80 や 443 などの Well-known ポートを使うには工夫が必要となる
  • 権限が狭まる分、Docker コンテナが上手く起動しないこともある

docker context lsで Docker のコンテキスト(接続先デーモン)の一覧と権限を確認できる。

アスタリスクの行のDOCKER ENDPOINTunix:///var/run/docker.sockであれば root 権限で動作している。

$ docker context ls
NAME        DESCRIPTION                               DOCKER ENDPOINT               ERROR
default *   Current DOCKER_HOST based configuration   unix:///var/run/docker.sock

Rootless モードをインストールする

Rootless mode | Docker Docs

$ sudo apt install uidmap

従属 UID/GID が 65536 以上であることを確認する。

$ grep ^$(whoami): /etc/subuid
ユーザー名:100000:65536
$ grep ^$(whoami): /etc/subgid
ユーザー名:100000:65536

root 権限の Docker デーモンが動いている場合は以下のコマンドを実行して止める。

# Dockerデーモン(docker.service)とソケット(docker.socket)を停止し、無効化する
$ sudo systemctl disable --now docker.service docker.socket

# Dockerソケットを削除する
$ sudo rm /var/run/docker.sock

ユーザーに Rootless モードをインストールする。ユーザー権限でインストールするので sudo は要らない。

$ /usr/bin/dockerd-rootless-setuptool.sh install

Rootless モード になっているか確認する。docker context lsを実行したとき、アスタリスクの行のDESCRIPTIONRootless modeであれば Rootless モードになっている。

$ docker context ls
NAME         DESCRIPTION                               DOCKER ENDPOINT                     ERROR
default      Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
rootless *   Rootless mode                             unix:///run/user/1000/docker.sock
$ systemctl --user restart docker.service

Rootless モードを無効にする

Rootless モードを元に戻したいときは、以下を実行する。

# RootlessモードのDockerのデーモンを停止する
$ systemctl --user stop docker.service
$ systemctl --user disable docker.service

# RootlessモードのDockerのソケットを削除する
$ sudo rm /run/user/1000/docker.sock

# コンテキストを通常に戻す
$ docker context use default

# Dockerを再起動する
$ sudo systemctl enable docker.service docker.socket
$ sudo systemctl restart docker.service docker.socket

# コンテキストを確認する
$ docker context ls
NAME         DESCRIPTION                               DOCKER ENDPOINT                     ERROR
default *    Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
rootless     Rootless mode                             unix:///run/user/1000/docker.sock

Rootless モードを有効にする

やっぱり Rootless モードにしたいときは、以下を実行する。

# Dockerのデーモンを停止する
$ sudo systemctl stop docker.service docker.socket
$ sudo systemctl disable docker.service docker.socket

# Dockerのソケットを削除する
$ sudo rm /var/run/docker.sock

# コンテキストをRootlessにする
$ docker context use rootless

# Dockerを再起動する
$ systemctl --user enable docker.service
$ systemctl --user restart docker.service

# コンテキストを確認する
$ docker context ls
NAME         DESCRIPTION                               DOCKER ENDPOINT                     ERROR
default      Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
rootless *   Rootless mode                             unix:///run/user/1000/docker.sock

Rootless モードで Well-known ポートを使う

Rootless モードで 80 や 443 などの Well-known ポートを使いたい場合、工夫が要る。

バイナリに Well-known ポートのバインド権限を与えることができるsetcapというコマンドがあるので、それが使える。

Rootless モードの Docker はrootlesskitを使ってポートフォワーディングを行うのでrootlesskitにバインド権限を与えれば良い。

# rootlesskitにWell-knownポートのバインド権限を与える
# cap_net_bind_service=ep: Well-knownポートのバインド権限をep(effective+permitted)
$ sudo setcap cap_net_bind_service=ep $(which rootlesskit)
$ systemctl --user restart docker.service

# 権限を確認する
$ getcap $(which rootlesskit)
/usr/bin/rootlesskit cap_net_bind_service=ep

# 権限を削除する
$ sudo setcap -r $(which rootlesskit)
$ systemctl --user restart docker.service

Rootless モードの Docker デーモンを常駐させる

Rootless モードならではの注意点の一つとして、SSH セッションを閉じるとDocker デーモンが終了してしまうことがある。

何故かというと、Rootless モードの Docker デーモンは~/.config/systemd/user/docker.serviceで起動しており、これは systemd のユーザーサービスであり、systemd のユーザーサービスは SSH セッションを閉じると終了してしまうからである。

しかし以下のコマンドでユーザーサービスの常駐を有効化することで、SSH セッションを閉じても Rootless モードの Docker デーモンを起動し続けることができる。

# ユーザーサービスの常駐を有効化する
$ sudo loginctl enable-linger $(whoami)

# 常駐の状態を確認する
$ loginctl show-user $(whoami) --property=Linger
Linger=yes

# ユーザーサービスの常駐を無効化する
$ sudo loginctl disable-linger $(whoami)

コンテナを非 root 権限で動作させる

docker

--user: 1000:1000で Docker を動かしているユーザと同じ権限で動作させることができる。

docker-compose.yml

user: 1000:1000で Docker を動かしているユーザと同じ権限で動作させることができる。

コンテナの実行権限を確認する

コンテナがどの権限で動いているかは以下のコマンドで確認できる。

$ docker exec $CONTAINER_NAME id
uid=0(root) gid=0(root) groups=0(root)
2
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?