私はDockerで実行しているCentOSイメージ上のサービスをリストしようとしています
systemctl list-units
しかし、私はこのエラーメッセージを受け取ります:
Failed to get D-Bus connection: Operation not permitted
問題が何であるかについての提案はありますか?
私の推測では、non-privileged
コンテナを実行しています。 systemdはCAP_SYS_ADMIN機能を必要としますが、Dockerはセキュリティを強化するために、非特権コンテナでその機能を削除します。
systemdには、ROコンテナー内のcgroupファイルシステムへのアクセス権も必要です。–v /sys/fs/cgroup:/sys/fs/cgroup:ro
で追加できます。
そこで、Dockerコンテナー内でsystemdを使用してCentOSを実行する方法のいくつかのステップを次に示します。
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"]
docker build --rm -t centos7-systemd - < mydockerfile
docker run --privileged -ti -e container=docker -v /sys/fs/cgroup:/sys/fs/cgroup centos7-systemd /usr/sbin/init
でコンテナを実行する
コンテナにsystemdが必要です
これはあなたの質問に対する直接の回答ではありませんが、実際にはもっと重要かもしれません。私はここで他の回答を読んでいるときにこの認識に出会いました。
私はいくつかの複雑なシステムを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
_が作成されます。 。
Systemdをinit/PID 1として起動する必要はありませんでした。他の人が述べたクリーンアップ手順を実行した後、起動スクリプト内から/usr/lib/systemd/systemd --system &
としてsystemdを起動します。
これにより、systemdは登録されたサービスを開始および起動できましたが、systemctlはD-Busエラーで失敗しました。
私にとって、失われたリンクは/ run/systemd/systemディレクトリの欠如でした。これはstrace
ing systemctlによって発見されました。
Systemctlを実行する前にこのディレクトリを手動で作成すると、systemctlが動作するようになります。