3
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

コンテナで`systemctl`を叩いたら`Failed to get D-Bus connection: No such file or directory`と言われた

Posted at

うっかり(でもない)Dockerをアップデートしたら、これまで動いていたコンテナのApacheが動かなくなって四苦八苦した際の備忘録です。

結論としては、コンテナでsystemctlコマンドを使うのをやめました。

以下環境での話です。

# Dockerを動かしている環境
WSL2 (Ubuntu 20.04.5 LTS)
# Dockerのバージョン
Docker version 23.0.3, build 3e7cbfd
# docker-composeのバージョン
docker-compose version 1.29.2, build 5becea4c

Docker Desktop for Windowsを使用していましたが、ある日それ自体がエラーで起動しなくなり、アンイストールして最新のDocker Desktop for Windowsをインストールし直したら、それまで動いていたWebサーバ(Apache)コンテナが動かなくなったのでムキーッ:grimacing:となりCLIに移行してみたものの同様の事象は解消されず、解決を試みたという話です。

ちなみにこの仮想環境は前任者の方が作成したもので、自分は今回初めてじっくり読み込んだ感じです(そのため言い回しが推量になっている箇所があります)。

ディレクトリ構成とソースコード

以下のような構成でした。
実際にはMySQLコンテナとアプリケーションのソースコードを配置するディレクトリもありましたが、今回の説明ではそちらは割愛。

├── app
│   ├── Dockerfile
│   ├── httpd
│   │   ├── conf
│   │   │   └── httpd.conf
│   │   └── conf.d
│   │       └── project.conf
│   └── index.html
└── docker-compose.yml

docker-compose.yml

docker-compose.ymlの設定は以下の通り。
コンテナ内でsystemctlコマンドを使用するために、コンテナを特権モードで実行するように指定されていました(privileged: true)。

docker-compose.yml
version: "3"
services:
  app:
    ports:
      - 8000:80
    container_name: test_app
    build: ./app
    # コンテナを特権モードで実行する
    privileged: true
    command: /sbin/init

Dockerfile

上記test-appコンテナのDockerfileは以下。
実際のDockerfileではPHPのインストール等を行っていましたが、今回の本筋ではないため最小限にしています。

ざっくり言うと、Apacheをインストールし、起動させるようにしています。

Dockerfile
FROM amazonlinux:2

RUN yum update -y && \
    yum install -y \
    # 確認用にpsコマンドを使用するためインストール
    procps \
    # Apacheのインストール
    httpd
    
# Apache設定ファイルの配置
COPY httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf
COPY httpd/conf.d/project.conf /etc/httpd/conf.d/project.conf

# 動作確認用のindex.htmlを配置
COPY ./index.html /var/www/html/index.html

# サービス自動起動有効
RUN systemctl enable httpd.service

RUN yum clean all && rm -rf /var/cache/yum/*

# Apache start
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
確認用のindex.html

確認用のindex.htmlはHello World!を出力するだけのものです。

index.html
<html>
    <body>
        Hello World!
    </body>
</html>

発生した事象

コンテナのビルドも起動もエラーなく完了しますが、ブラウザでhttp://localhost:8000へアクセスしても「このページは動作していません」とだけ表示され、想定の画面が表示されません。

コンテナのApacheエラーログを確認しますが、そもそもエラーログが出力されていません。

Apacheが動いていないのでは?と思い状態を確認しようとsystemctlコマンドを叩いたら、見慣れないエラーメッセージに遭遇しました。

$ systemctl status httpd
Failed to get D-Bus connection: No such file or directory

ちなみにpsコマンドの結果は以下です。

bash-4.2# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0  40604  3456 ?        Ss   02:50   0:00 /sbin/init
root           7  0.2  0.0  11700  2924 pts/0    Ss   02:51   0:00 bash
root          13  0.0  0.0  49808  3280 pts/0    R+   02:51   0:00 ps aux

Dockerとsystemd

そもそもsystemctlとはsystemdシステムおよびサービスマネージャーを操作するためのコマンドです。systemdを簡単に言うとシステムの管理をしてくれるやつ。OSが最初に生成するプロセスであり(systemdのPIDは1)、全てのプロセスの創始。きちんと説明できる自信がないので概要of概要に止めておきます(勉強しよ...)。

ただし、Dockerではsystemdを利用することができないということです。何故?の部分に触れている記事等が少なかったのですが、以下では2点挙げられています。

理由1: cgroupsの壁
まず、Systemdは、LinuxのcgroupsというKernel提供の機能に依存しているのですが、通常のDocker containerはそもそもcgroupsの機能を使って隔離された環境で動作するため、cgroups自体を操作する権限が限定されてしまいます。

理由2: initの壁
そもそもDockerコンテナはinitから起動しない(initがない)ので、initプロセスに依存するスクリプトは軒並み動きません。serviceコマンドで操作できないサービスは、たいていこれが原因です。
daemon化を前提とするサービスの多くがこの影響を受けます。PID 1のinitプロセスを前提としてdaemon化するプログラムは動作しません。

そして「コンテナでsystemctlコマンドを使う」ための方法として記事等でよく挙げられているのが、コンテナを特権モードで実行するです。

先述のソースコードで言えば、docker-compose.yml内の以下がそれにあたります。

docker-compose.yml(抜粋)
    # コンテナを特権モードで実行する
    privileged: true
    command: /sbin/init

「コンテナを特権モードで実行する」とは

自分もこの「コンテナを特権モードで実行する」が何のか知らなかったのですが、調べてみるとそれはコンテナ(プロセス)にホストの特権(root)ユーザーと同等の権限を持たせるということが分かりました。

これだけでもうなんか(セキュリティ的に)アカン匂いがする...:innocent:

(そして「コンテナ 特権」とかでググると危険性を指摘する記事が多いので察する。)

そもそも特権コンテナはsystemctlコマンドを使うために設定されていたので、systemctlコマンドを利用せずに(特権コンテナにもせずに)Apacheを起動する方法に切り替えようと思いました。

ソースコードを修正

docker-compose.ymlの修正

docker-compose.ymlからコンテナを特権モードで実行させる箇所の記述を削除します。

docker-compose.yml
- # コンテナを特権モードで実行する
- privileged: true
- command: /sbin/init

Dockerfileの修正

Dockerfileからはsystemctlを使用している箇所を削除します。

Apacheの起動はCMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]の箇所でできるため追記は不要です。

Dockerfile
- # サービス自動起動有効
- RUN systemctl enable httpd.service
最終的なソースコード
docker-compose.yml
version: "3"
services:
  app:
    ports:
      - 8000:80
    container_name: test_app
    build: ./app
Dockerfile
FROM amazonlinux:2

RUN yum update -y && \
    yum install -y \
    # 確認用にpsコマンドを使用するためインストール
    procps \
    # Apacheのインストール
    httpd
    
# Apache設定ファイルの配置
COPY httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf
COPY httpd/conf.d/project.conf /etc/httpd/conf.d/project.conf

# 動作確認用のindex.htmlを配置
COPY ./index.html /var/www/html/index.html

RUN yum clean all && rm -rf /var/cache/yum/*

# Apache start
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

動作確認用に配置したindex.htmlがブラウザから確認できました:cherry_blossom:

screenshot_01.jpg

psコマンドからもhttpdプロセスが確認できました:cherry_blossom:

bash-4.2# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.1 249200  9120 ?        Ss   02:55   0:00 /usr/sbin/httpd -D FOREGROUND
apache         7  0.0  0.1 486984  8336 ?        Sl   02:55   0:00 /usr/sbin/httpd -D FOREGROUND
apache         8  0.0  0.0 290448  6876 ?        Sl   02:55   0:00 /usr/sbin/httpd -D FOREGROUND
apache        10  0.0  0.0 290312  6292 ?        Sl   02:55   0:00 /usr/sbin/httpd -D FOREGROUND
apache        17  0.0  0.0 290312  6292 ?        Sl   02:55   0:00 /usr/sbin/httpd -D FOREGROUND
apache        37  0.0  0.0 290312  6292 ?        Sl   02:55   0:00 /usr/sbin/httpd -D FOREGROUND
apache        53  0.0  0.0 290312  6300 ?        Sl   02:55   0:00 /usr/sbin/httpd -D FOREGROUND
root          59  0.5  0.0  11700  2880 pts/0    Ss   03:07   0:00 bash
root          65  0.0  0.0  49808  3344 pts/0    R+   03:07   0:00 ps aux

まとめのようなひとりごと

なぜそれまで動いていたコンテナのApacheが動かなくなったのか?のなぜ、については解明できていないのですが、調べを進める内に現状のコンテナの作りがあまり良いものではないものだということが分かりました。

たしかに同プロジェクトの運用環境ではAmazon EC2インスタンスのAmazon Linux 2上にApacheMySQLを動かしているためsystemctlでの起動が必要です。
しかしコンテナの考え方では、1つのコンテナで動かすのは1つのプロセスの想定なので、複数のプロセスを管理するためのsystemdを必要としないのだなと思いました。

そう考えると運用環境もコンテナで動くようにしたほうがいいのかな(専門外だが一回やってみたい感がある)、そもそも読み込むイメージがamazonlinuxではなくhttpdイメージにすることはできないのか、とか色々思うところがありました。もっと良い提案ができるだけの知識を身に付けたいです。

Dockerを中心としたコンテナ技術や仮想環境についてはまだまだ勉強中ですが、Linux周りのこともまだまだ...勉強します。

参考サイト 

3
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?