7
6

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を考える

7
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

最後にDockerデーモンを再起動する。

$ 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モードを有効にする

上記の手順は恒久的にモードを切り替える方法だが、ターミナルを開いている間だけRootlessモードを有効にしたいときもある。

そういうときは以下を実行する。

$ export DOCKER_CONTEXT=rootless

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 セッションを閉じると終了してしまうのである。

このことを知らないと、例えばWebアプリケーションのコンテナをRootlessモードで起動して喜ぶもSSHセッションを閉じたら応答が無くなってしまった、という事態に出くわす。

対処法としては以下のコマンドでユーザーサービスの常駐を有効化させる。これによりSSHセッションを閉じてもRootlessモードのDockerデーモンを起動し続けることができる。

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

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

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

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

各ツールにオプションを指定してやることで、コンテナを非root権限で動作させることができる。

$UIDはユーザーID、$GIDはグループIDを示す。

なお自分のユーザーID、グループIDはidコマンドで確認できる。

docker

--user: $UID:$GIDでユーザーを指定できる。

Dockerfile

USER $UID:$GIDでユーザーを指定できる。

docker-compose.yml

user: $UID:$UIDでユーザーを指定できる。

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

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

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?