このすみ技術ろぐ

とあるWebエンジニアが、技術や趣味について書くブログです。

『Failed to get D-Bus connection: Operation not permitted』で、CentOS 7のdockerでPostgreSQLの起動が失敗した件

さきほどの話ですが、PostgreSQLのコマンドを確認したかったので、PostgreSQLをインストールしました。 ちょうどLinuxコマンドの動作確認用に、手元でCent OS 7のDockerを起動していたので、そこにインストールして起動します。

イメージとしては、こんな感じです。

$ docker run -it centos:centos7 /bin/bash
[root@15eba360665a /]# whoami
root
[root@15eba360665a /]# yum install postgresql-server
...
Installed:
  postgresql-server.x86_64 0:9.2.24-4.el7_8
...
[root@15eba360665a /]# systemctl start postgresql
Failed to get D-Bus connection: Operation not permitted

PostgreSQLを起動しようとしたのですが、見事に失敗しました。

Failed to get D-Bus connection: Operation not permitted

エラーメッセージで検索したところ、2つの原因がわかりました。

  • リソースへのアクセス権限が足りない
  • systemdが起動していない

上記のエラーを解決する方法

同じエラーに遭遇した方のページに、解決方法が書いてありました。

$ docker run -d --privileged --name docker_test centos /sbin/init
$ docker exec -it docker_test /bin/bash
# yum install -y httpd
# systemctl start httpd
# systemctl status httpd

DockerでCentOS7起動時にsystemctlが動かないとき
普通に適当(雑の方の意味)に起動するだけだと動かないのです。
対策として下記の3つを使用することで、systemctlが使用できるようになります。

  • --privilegedを使用する。
  • /sbin/initで起動する。
  • 上記に合わせ、-itではなく-dで起動し、起動後にexecする。

https://www.tcmobile.jp/dev_blog/devtool/docker%E3%81%A7centos7%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%AEsystemctl%E3%81%8C%E5%8B%95%E3%81%8B%E3%81%AA%E3%81%84%E3%81%A8%E3%81%8D/ より

-—privilegedを使用する

systemctl実行時のエラーメッセージには、「D-Bus connection: Operation not permitted」と書いてあります。 このことから、権限が足りてないことまではわかります。

そこで登場するのが、『--privileged』というコマンドオプションです。 『privileged』は日本語に訳すと特権という意味で、起動するコンテナに特権を付与します。

2.コンテナに特権を与える場合
コンテナからホスト上のファイルへアクセスする際に最も簡単なものがこちらです。
コンテナに特権を付与することで、ホスト上のすべてのデバイスへのアクセスする権限が与えられます。
以下のようにdocker runのオプションとして「--privileged」と入力すると特権が付与されます。
https://armadillo.atmark-techno.com/blog/10899/4191 より

privilegedは危険を伴うオプションである

『--privileged』を付与することによって、無事にPostgreSQLを起動することに成功しました。 しかしながら、さらに調査を続けたところ、『--privileged』は危険を伴うオプションのようです。

Dockerコンテナを特権モードで実行することが危険な理由
Docker の「Privileged(特権)」コンテナ(以下、特権コンテナ)は、簡潔に言えば、ホストコンピュータに対するすべてのルート権限を備えたコンテナであり、通常のコンテナではアクセスできないリソースへのアクセスが可能となります。
https://blog.trendmicro.co.jp/archives/23577 より

トレンドマイクロ社が専用記事で警告しているくらいですから、鬼気迫るものがあります。 『--privileged』は、あくまで今回のような一時的な使用に限定し、本番環境で使用しないほうが無難です。

/sbin/init経由で、systemdを起動する

initはLinuxカーネルの起動後、最初に実行されるプロセスです。 Qiitaのinitまとめ(ざっくり)が、簡潔にまとめてありオススメです。

initとは

  • initは他のプロセスを起動させる役割を持っており, 全てのプロセスの親である.
  • Linuxカーネルの起動後, 一番最初に起動される.
  • PIDは1が付与されている.

https://qiita.com/h_tyokinuhata/items/26b7dd3526e7061596b9 より

なお、実際にCent OS7で確認したところ、実体はsystemdへのシンボリックリンクになっておりました。

[root@0467571e7b9b ~]# ls -l /sbin/init
lrwxrwxrwx 1 root root 22 Aug  9 21:38 /sbin/init -> ../lib/systemd/systemd

単純に起動したdockerコンテナは、必要最小限のプロセスしか実行されない

『/sbin/init』のプロセスが起動していないことは、実際にプロセスを確認するとわかります。 コンテナ実行時に指定したコマンド以外は、見事に何もプロセスがありません。

$ docker run --rm -it centos:centos7 /bin/bash
[root@d0090488dced /]# ps axuw -w
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  5.0  0.1  11840  2876 pts/0    Ss   08:02   0:00 /bin/bash
root        14  0.0  0.1  51768  3540 pts/0    R+   08:02   0:00 ps axuw -w

まとめ

Dockerコンテナは、必要最小限の権限付与とプロセスしか起動しないため、通常のサーバーとは異なる特性があります。 本記事のようなケースでは、素直に公式のPostgreSQLイメージを使おうと心に誓いました。