やりたかったこと(または「症状」)

新しく借りたVPSにDockerをaptでインストールし、公式ドキュメント通りに動作確認をしようとした。sudoなしでdocker psを叩いたところ、コンテナ一覧どころか以下のエラーで止まった。

docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.45/containers/json": dial unix /var/run/docker.sock: connect: permission denied

インストール自体はClient: Docker Engine - CommunityServer:のバージョン情報が両方表示されており失敗していないように見えたので、なぜdocker ps単体がこけるのか最初は理解できなかった。

環境

  • OS: Ubuntu 22.04.4 LTS(さくらのVPS)
  • Docker Engine: 26.1.4
  • Docker Compose: v2.27.0
  • ログインユーザー: deploysudo権限はあるが非root)
  • インストール方法: get.docker.com公式スクリプト経由

試したこと

最初は毎回sudoを付ければいいと考え、sudo docker psで回避していた。これは動くが、後でdocker-compose.ymldeployユーザーの権限で自動デプロイするGitHub Actionsのself-hosted runnerから叩いた際、runnerのスクリプトにsudoのパスワードプロンプトを挟めず、そのままジョブが停止してしまった。

次に、根本解決のつもりで/var/run/docker.sockのパーミッションを直接書き換えた。

sudo chmod 666 /var/run/docker.sock
docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS   PORTS   NAMES

このときはsudoなしでdocker psが通り、解決したと思って作業を進めた。ところが翌日にVPSを再起動したところ、まったく同じpermission deniedエラーが復活した。chmodで直接変更したパーミッションは、dockerdがソケットを再生成するたびに初期値へ戻されるため、再起動のたびに設定し直す必要があり、恒久対策にならないと分かった。

原因

Dockerデーモンは/var/run/docker.sockというUnixソケット経由でクライアントからの要求を受け付ける。このソケットはroot:dockerの所有・グループで作成され、パーミッションは660(所有者とグループのみ読み書き可)に設定される。ログインユーザーがdockerグループに所属していない場合、root権限を持つプロセス(sudo経由)以外はこのソケットにアクセスできず、permission deniedとなる。chmodでその場のパーミッションを変えても、dockerdの起動・再起動時にsystemdのソケットユニットがデフォルト値でソケットを作り直すため、変更は永続しない。

解決方法

1. ユーザーをdockerグループに追加する

sudo usermod -aG docker $USER

このコマンド自体はエラーなく完了するが、この時点ではまだ現在のシェルセッションのグループ情報は更新されていない。

2. グループ変更を反映させる

ログアウトして再ログインするか、newgrpでグループ変更をそのセッションに反映する。

newgrp docker
groups
deploy sudo docker

groupsの出力にdockerが含まれていれば、現在のシェルがdockerグループの権限を持った状態になっている。ログインシェルのグループ情報はログイン時に決定されるため、usermodだけでは反映されず、セッションの再作成(再ログインまたはnewgrp)が必要になる。

3. sudoなしで動作確認する

docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS   PORTS   NAMES

sudoを付けずにdocker psがエラーなく完了すれば、docker.sockへのアクセス権が正しく付与されている。この方法はsystemdによるソケット再生成の影響を受けないため、再起動後も設定し直す必要がない。

ハマったポイント

  • usermod -aG docker $USERを実行した直後、同じターミナルのままdocker psを叩いて「直っていない」と勘違いした。グループ情報はログインシェル起動時に固定されるため、同一セッション内では反映されない
  • chmod 666 /var/run/docker.sockで一時的に解決したように見えたが、VPSを再起動した翌日に同じエラーが再発した。dockerdの再起動でソケットが作り直され、パーミッションが660に戻っていた
  • dockerグループへの追加は事実上rootと同等の権限を与えることになる、という点を後から知った。dockerグループのユーザーはホストのファイルシステムをマウントしたコンテナを起動できるため、root権限昇格の経路になり得る
  • GitHub Actionsのself-hosted runnerをdeployユーザーで動かしていた際、runnerのプロセスがusermod実行前に起動していたため、グループ変更後もrunnerサービス自体を再起動するまで反映されなかった

よくある質問

Q: dockerグループにユーザーを追加するのはセキュリティ的に安全ですか? dockerグループのメンバーは、ホストの任意のディレクトリをマウントしたコンテナを起動できるため、実質的にroot権限を持つのと同等になる。信頼できる個人開発環境や検証用VPSでは一般的な運用だが、複数人が共有するサーバーでは慎重に権限を絞る必要がある。

Q: サーバーを再起動せずに今すぐ反映したいです。 newgrp dockerを実行すれば、そのシェルセッション内だけグループ変更を即座に反映できる。別のターミナルやSSHセッションには影響しないため、恒久的に反映したい場合は最終的にログアウト・再ログインが必要になる。

Q: WSL2上のDocker Desktopでも同じ手順で直りますか? Docker DesktopのWSL2統合を使っている場合、/var/run/docker.sockはWindows側のDocker Desktopエンジンからプロキシされているため、WSL内でusermodしても解決しないことがある。その場合はDocker Desktopの設定にある「Resources > WSL Integration」で対象のディストリビューションを有効化する必要がある。

関連記事