Dockerでの「Failed to get D-Bus connection」エラーの解決方法

intermediate🐳 Docker2026-07-10| Docker Engine, CentOS 7/8, Ubuntu 18.04+, Debian、およびその他のsystemdベースのコンテナ。

Error Message

Failed to get D-Bus connection: Operation not permitted
#docker#systemd#devops#linux管理

問題点:systemctlが失敗する理由CentOSやUbuntuのコンテナ内で、Nginx、Apache、データベースなどのサービスを起動しようとしているかもしれません。systemctl startを実行しても、サービスが起動する代わりに、ターミナルにFailed to get D-Bus connection: Operation not permittedというエラーが表示されます。

これは、Dockerコンテナが軽量で隔離されるように設計されているためです。デフォルトでは、ホストのsystemdと通信したり、自身のsystemdインスタンスを管理したりする権限がありません。systemdは最初のプロセス(PID 1)として動作することを想定しており、機能するためにはホストのコントロールグループ(cgroups)への直接アクセスが必要です。標準のDockerセキュリティプロファイルは、ホストの安全を守るためにこのアクセスをブロックしています。

クイックフィックス:特権モードの使用systemdを動作させるには、Dockerのデフォルトの制限を解除する必要があります。これには、コンテナに拡張特権を付与し、systemdがプロセスを正しく管理できるようにホストのcgroupディレクトリをマウントすることが含まれます。

以下のフラグを使用してコンテナを起動します:

docker run -d \  --name web-server \  --privileged \  -v /sys/fs/cgroup:/sys/fs/cgroup:ro \  centos:7 /usr/sbin/init

コマンドの解説:- --privileged: コンテナにホストのハードウェアおよびカーネル機能へのほぼ完全なアクセス権を付与します。- -v /sys/fs/cgroup:/sys/fs/cgroup:ro: ホストのコントロールグループをコンテナ内にマップします。これがないと、systemdはサービスのリソースを追跡したり制限したりできません。- /usr/sbin/init: 最も重要な部分です。単にbashシェルを起動するのではなく、systemdのinitプロセスをPID 1として開始するようDockerに指示します。## Docker Composeによる自動化長いdocker runコマンドを手動で入力するのは面倒です。この設定を固定したい場合は、docker-compose.ymlファイルにこれらのパラメータを追加します。これは、スタックを頻繁に再起動するローカル開発環境で特に便利です。

version: '3' 
services:
  app-server:
    image: centos:7
    privileged: true
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
    command: /usr/sbin/init

1つのコマンドで更新された設定をデプロイします:

docker-compose up -d

内部で何が起きているのか?Dockerは単一のアプリケーションプロセスを実行するように最適化されています。一方、systemdは数十のバックグラウンドサービスを監視するために設計されたマネージャー全体です。その役割を果たすために、systemdは「親」プロセス(PID 1)である必要があります。

標準的なコンテナを実行する場合、通常はシェル(bash)やアプリがPID 1になります。systemctlを使用しようとすると、PID 1と通信するためのD-Bus接続を探します。systemdが実際にはinitプロセスとして実行されていないため、接続は失敗します。/usr/sbin/init--privilegedを使用することで、実質的にコンテナを軽量な仮想マシンのように扱っています。

より軽量な代替案:--initフラグ本当にsystemctlが必要ですか?それとも単にプロセス管理が必要なだけですか?シグナル(SIGTERMなど)の処理やゾンビプロセスのクリーンアップだけが目的であれば、systemdのフル機能は不要です。Docker 1.13以降には、tiniと呼ばれる組み込みのinitプロセスが含まれています。

docker run -it --init ubuntu:20.04 /bin/bash

注意: アプリが厳密にsystemctlを必要とする場合、これはD-Busエラーを解決しません。しかし、本番環境でプロセス管理を行うには、より安全な方法です。

修正の確認特権フラグを付けてコンテナを起動した後、systemdが正常であることを確認します。まず、コンテナのターミナルに入ります:

docker exec -it web-server /bin/bash

次に、システムの状態を確認します:

systemctl status

すべてが正しく設定されていれば、State: runningとアクティブなユニットの一覧が表示されます。これで、物理サーバー上と同じようにサービスを開始できます:

systemctl start httpd
systemctl status httpd

セキュリティに関する警告--privilegedの使用は強力すぎる手段です。これにより、コンテナにホストマシンへのルートレベルのアクセス権が与えられます。本番環境では、これは重大なセキュリティリスクとなります。コンテナが侵害された場合、攻撃者がホストへ脱出する可能性があります。コンテナ内でsystemdを使用する前に、必ずDockerfileをリファクタリングして、アプリケーションを直接実行する(ENTRYPOINTを使用する)方法を検討してください。

Related Error Notes