web-dev-qa-db-ja.com

D-Bus接続の取得に失敗しました:操作は許可されていません

私はDockerで実行しているCentOSイメージ上のサービスをリストしようとしています

systemctl list-units  

しかし、私はこのエラーメッセージを受け取ります:

Failed to get D-Bus connection: Operation not permitted

問題が何であるかについての提案はありますか?

33
Snowcrash

私の推測では、non-privilegedコンテナを実行しています。 systemdはCAP_SYS_ADMIN機能を必要としますが、Dockerはセキュリティを強化するために、非特権コンテナでその機能を削除します。

systemdには、ROコンテナー内のcgroupファイルシステムへのアクセス権も必要です。–v /sys/fs/cgroup:/sys/fs/cgroup:roで追加できます。

そこで、Dockerコンテナー内でsystemdを使用してCentOSを実行する方法のいくつかのステップを次に示します。

  1. CentOS画像をプル
  2. 以下のようなDockerファイルを設定します。
FROM centos
MAINTAINER "Yourname" <[email protected]>
ENV container docker
RUN yum -y update; yum clean all
RUN yum -y install systemd; yum clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
  1. ビルド-docker build --rm -t centos7-systemd - < mydockerfile
  2. docker run --privileged -ti -e container=docker -v /sys/fs/cgroup:/sys/fs/cgroup centos7-systemd /usr/sbin/initでコンテナを実行する

  3. コンテナにsystemdが必要です

28
13dimitar

これはあなたの質問に対する直接の回答ではありませんが、実際にはもっと重要かもしれません。私はここで他の回答を読んでいるときにこの認識に出会いました。

私はいくつかの複雑なシステムをDockerに移行した経験があり、重要な認識の1つは、理想的にはアプリケーション/サービスごと、または「デーモンごと」に1つのDockerコンテナーが必要であることです。

これの非常に重要な理由の1つは、Dockerがsystemctlで開始するサービスを完全にシャットダウンせず、実際に同じ種類のデータベースになる可能性があることです予期しない停電による破損。

これについてもう少し詳しく説明します。Dockerがコンテナに「stop」コマンドを発行すると、SIGTERMシグナルは、すべてのサービスとデーモンではなく、CMD/ENTRYPOINTで開始された単一のプロセスのみに送信されます。そのため、1つのサービスが正常にシャットダウンするように警告し、他のすべてのサービスは不正に終了します。

同じコンテナに2つのサービスを絶対にパッケージ化する必要がある場合(つまり、アプリケーションとPostgreSQLデータベースなど)、CMD/ENTRYPOINTをSIGTERMをキャッチし、それらを既知のサービスに再ブロードキャストするスクリプトにする必要があります。それは可能ですが、機会があれば、ソリューションを再考して、複数のコンテナに分割してみてください。

補遺

同じコンテナで複数のサービスを実行する必要がある場合に、supervisordを使用することについて興味深い Dockerサイトの注/ページ があります。

CentOS:7 Dockerコンテナでこの問題を解決できました。私は主に CentOS Dockerイメージプロジェクトのガイド に従いました。

_FROM centos:7

ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;

# Install anything. The service you want to start must be a SystemD service.

CMD ["/usr/sbin/init"]
_

次に、イメージをビルドし、少なくとも以下の_docker run_コマンドの引数を使用して実行します。_-v /run -v /sys/fs/cgroup:/sys/fs/cgroup:ro_

次に重要な点は、_/usr/sbin/init_はDockerコンテナー内の最初のプロセスでなければならないということです。

したがって、_/usr/sbin/init_を実行する前にいくつかのコマンドを実行するカスタムスクリプトを使用する場合は、_exec /usr/sbin/init_を使用して(bashスクリプトで)スクリプトの最後に起動します。

次に例を示します。

_ADD cmd.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/cmd.sh

CMD ["/usr/local/bin/cmd.sh"]
_

そして、これが_cmd.sh_の内容です:

_#!/bin/bash

# Do some stuffs

exec /usr/sbin/init # To correctly start D-Bus thanks to https://forums.docker.com/t/any-simple-and-safe-way-to-start-services-on-centos7-systemd/5695/8
_

PAMシステムを使用している場合はSystem is booting up. See pam_nologin(8)を使用できます。その場合、Dockerfileで_/usr/lib/tmpfiles.d/systemd-nologin.conf_を削除します。これにより、この特定のエラーを生成するファイル_/var/run/nologin_が作成されます。 。

3
Anthony O.

Systemdをinit/PID 1として起動する必要はありませんでした。他の人が述べたクリーンアップ手順を実行した後、起動スクリプト内から/usr/lib/systemd/systemd --system &としてsystemdを起動します。

これにより、systemdは登録されたサービスを開始および起動できましたが、systemctlはD-Busエラーで失敗しました。

私にとって、失われたリンクは/ run/systemd/systemディレクトリの欠如でした。これはstraceing systemctlによって発見されました。

Systemctlを実行する前にこのディレクトリを手動で作成すると、systemctlが動作するようになります。

1
Chaim Geretz