午前2時の電話と、root権限という特権の代償
午前2時、監視システムからの真っ赤なアラート通知でスマートフォンの画面が明るくなりました。ステージング環境のコンテナが1つ、侵害(compromised)されたのです。攻撃者は、チームが更新しきれていなかった古いライブラリのRCE(遠隔コード実行)の脆弱性を突くことに成功していました。
恐ろしいのは、Dockerデーモンがデフォルトでroot権限で動作している点です。攻撃者がコンテナ脱出(container breakout)に成功すれば、物理サーバー上の最高権限を即座に手に入れることになります。これは、家の鍵を厳重に閉めているのに、合鍵を玄関マットの下に置いているようなものです。
その一件以来、私はすべてのサービスをRootless Modeに移行しました。これは最小権限の原則(Least Privilege)を徹底的に適用する方法です。Dockerデーモンにroot権限がなければ、攻撃者がコンテナから脱出したとしても、ただの権限のないユーザーに過ぎず、システムの核心部を破壊することはできません。Dockerコンテナのセキュリティ全般についてのベストプラクティスと組み合わせることで、より強固な防御層を構築できます。
5分で完了するDocker Rootlessのインストール
脆弱性が見つかるのを待つのではなく、今すぐプロアクティブにサーバーを保護しましょう。UbuntuやDebianであれば、わずか数ステップで設定が完了します。
ステップ1:環境の準備
Rootless Dockerには、ユーザーIDをマッピングするためのnewuidmapとnewgidmapが必要です。以下のコマンドでこれらの補助パッケージをインストールします。
sudo apt-get update
sudo apt-get install -y dbus-user-session uidmap slirp4netns fuse-overlayfs
ステップ2:インストールスクリプトの実行(sudoは使用しない)
Dockerは非常に軽量な自動インストールスクリプトを提供しています。このコマンドは必ず一般ユーザーとして実行してください。コマンドの前に絶対にsudoを付けないでください。
curl -fsSL https://get.docker.com/rootless | sh
ステップ3:環境変数の宣言
スクリプトの実行が完了すると、いくつかの設定行を追加するよう求められます。ログインするたびにDockerが自動的に有効になるよう、これらを.bashrcまたは.zshrcファイルにコピーしてください。
export PATH=/home/$USER/bin:$PATH
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
新しい設定を有効にするには、source ~/.bashrcを実行します。
ステップ4:接続の確認
コンテナを起動して、すべてが正常に動作しているか確認します。
docker run -d hello-world
sudoを使わずに「Hello from Docker!」というメッセージが表示されれば、あなたのシステムは世の中のデフォルト設定のサーバーよりも90%以上安全になったと言えます。
Rootless Modeのセキュリティメカニズムは何が特別なのか?
通常モードでは、dockerdプロセスがroot権限を保持しています。作成されるすべてのコンテナは、ホスト上の最高権限を持つ実体によって管理されます。一方、Rootless ModeはLinuxカーネルのユーザー名前空間(User Namespaces)を活用します。
この機能は、コンテナ内部のUID(ユーザーID)をホストマシン上の別のUIDにマッピングします。例えば、コンテナ内のrootユーザー(UID 0)は、実際にはホスト外のユーザーthanh_it(UID 1001)と同等になります。
以前、Memcachedの脆弱性を経由して侵入したマイニングボットの対応をしたことがあります。Rootfulモードでは、そのボットがCPUを400%まで跳ね上げ、APIのレイテンシを50msから10sに悪化させ、システムを麻痺させました。Rootlessであれば、リソース制限をユーザーレベルで厳格に行うことができます。docker statsとcAdvisorを使ったリソース監視と組み合わせることで、異常なCPU・RAM消費をいち早く検知できます。また、攻撃者は悪意のあるプロセスを隠すためにカーネルの深部に干渉することもできません。
Rootless実行時によくある3つの障壁
Rootlessへの移行は、すべてが「バラ色」というわけではありません。インフラ面でいくつか対処が必要な制限があります。
1. 1024未満のポート制限
Linuxのデフォルトでは、rootのみが1から1023までのポートをバインドできます。ポート80でNginxを実行しようとすると、Dockerは即座にPermission deniedエラーを吐き出します。
解決策: 8080や8443などの高いポート番号でコンテナを実行してください。その後、リバースプロキシやCloudflare Tunnelを使用してトラフィックを誘導します。どうしても低いポートを使用する必要がある場合は、以下のコマンドを実行して一般ユーザーに権限を解放します。
sudo sysctl net.ipv4.ip_unprivileged_port_start=80
2. Pingコマンドのエラー
コンテナ内からping google.comができないことがあっても驚かないでください。これは、ネットワーキングメカニズムであるslirp4netnsがデフォルトでRAWソケットを作成する権限を持っていないためです。Dockerのネットワーキングモード(Bridge・Host・Overlay)の違いを理解しておくと、この種のトラブルシューティングがスムーズになります。
解決策: カーネルの許可ポート範囲を以下のコマンドで再設定します。
sudo sysctl -w net.ipv4.ping_group_range="0 2147483647"
3. リソース制限(Cgroup v2)
CentOS 7のような古いディストリビューションでは、RootlessコンテナのRAMやCPUを制限しようとすると苦労することになります。すべてをスムーズに運用するためには、Cgroup v2を標準でサポートしているUbuntu 22.04やDebian 11以降の使用をお勧めします。
本番環境でRootlessを運用するためのコツ
紆余曲折を経て得られた、システムをより安定して管理するための3つの貴重な経験則を紹介します。
- ログアウト後もサービスを維持する: Dockerはユーザー権限で動作しているため、SSHセッションを終了すると停止してしまいます。デーモンを永続的にバックグラウンドで実行させるには、
lingering機能を有効にします:sudo loginctl enable-linger $USER。 - 容量管理: Dockerのデータはデフォルトで
~/.local/share/dockerに保存されます。/homeパーティションの空き容量をよく確認してください。必要に応じて、シンボリックリンクを使用してこのディレクトリを別のデータ用ディスクに移動させましょう。 - バックアップ時の注意: ボリュームのバックアップに
sudo cpを使わないでください。これを行うとファイルの所有権(UIDマッピング)が狂ってしまい、リストア後にコンテナを再起動できなくなる可能性があります。Docker Volumesによるデータ永続化の仕組みを正しく理解することで、こうした所有権トラブルを未然に防げます。
最初はsudoを使わない習慣に戸惑うかもしれません。しかし、Rootlessの設定に費やす30分は、あなたの安心のための最も安上がりな投資です。システムが侵入されてから慌ててパッチを当てるような事態は避けましょう。

