Docker で手動で手順を確認しつつ Apache にアクセスできるようになるまで (Failed to get D-Bus connection: Operation not permitted 対処含む)

docker-composesystemctl からの Apache の起動が上手く行かず (Failed to get D-Bus connection: Operation not permitted が出てしまう) 、手動でコマンドを一つずつ確認しながら Docker 環境の検証をしてみることにしました。

ちなみに環境は Docker for Windows 下で、バージョンは以下の通りとします。

> docker --version
Docker version 20.10.2, build 2291f61

検証

まずは CentOS7 のイメージから起動します。ローカルに centos:7 が既にある状態とします。

> docker run -it centos:7 /bin/bash

これでコマンドを入れていきます。今回は httpd-devel を入れます。

# yum -y update && yum -y install epel-release sudo less iproute openssh-clients httpd-devel

いくつか設定ファイルを除外。

# mv -i /etc/httpd/conf.d/autoindex.conf /etc/httpd/conf.d/autoindex.conf.org
# mv -i /etc/httpd/conf.d/userdir.conf /etc/httpd/conf.d/userdir.conf.org
# mv -i /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.org

現状ではサーバ名がないため、 /etc/httpd/conf/httpd.conf に追記します。ついでにバージョン情報を出さない設定もその後に追記できるかどうかのテストとして入れておきます。

# echo ServerName www.example.com:80 >> /etc/httpd/conf/httpd.conf
# echo ServerTokens Prod >> /etc/httpd/conf/httpd.conf

ここまでは上手く行くことが分かっているので、ひとまず fix します。

# exit

最初に docker run -it したときに --name オプションを付けなかったため適当なイメージ名でコンテナが上がっている (ここでは仮に XXXXX_XXXXXXXX とします) ことを Docker Desktop から確認 (docker ps でも可)。

その名前を自分で指定した名前で commit します。

> docker commit XXXXX_XXXXXXXX httpd_test_man
docker commit でここまでの作業分をイメージとして作成
docker commit でここまでの作業分をイメージとして作成

OK。イメージに登録されました。

これで再度コンテナに入ります。

> docker run -it httpd_test_man /bin/bash
#

今回は commit 時に指定した名前 httpd_test_man で入れました。

# systemctl enable httpd.service
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service, pointing to /usr/lib/systemd/system/httpd.service.
# systemctl start httpd.service
Failed to get D-Bus connection: Operation not permitted

まずは普通に systemctl してみます。 enable はできましたが、 start しようとすると

Failed to get D-Bus connection: Operation not permitted

エラーが発生することが確認できました。

ここで再び exit

> docker run -d --privileged -p 8080:80 --name httpd_test_man httpd_test_man /sbin/init

今度はオプションを変更したり追加したりしました。

  • docker run 時のオプションを -it から -d に変更
  • --privileged 追加
  • -p 8080:80 でポートフォワーディング
  • --name httpd_test_man httpd_test_man でイメージ名指定 (-d のときは付ける必要があるため)
  • /sbin/init 実行
> docker exec -it httpd_test_man /bin/bash

これでコンテナに入ります。

]# systemctl start httpd
# systemctl status httpd
● httpd.service - The Apache HTTP Server

## 略

起動できました。

127.0.0.1:8080 で Apache にアクセスできることを確認
127.0.0.1:8080 で Apache にアクセスできることを確認

上でポートフォワーディングしたように、 127.0.0.1:8080 でコンテナの Apache にアクセスできることが確認できました。

続いて hosts に以下のように追記します。

192.0.2.1    www.example.com #自PCのIPを www.example.com として追記
www.example.com:8080 で Apache にアクセスできることを確認
www.example.com:8080 で Apache にアクセスできることを確認

同じ結果になることは分かっていますが念のため。 www.example.com:8080 でアクセスできました。

これでひとまず、コマンドにオプションを付けて systemctl で Apache が起動できることは確認できました。

……そうすると、何故 docker-compose だとダメなのか……(いくつかの記事に書いてある方法を試してもダメで嵌まり中)。

備考 (本題)

Dockerfile

まず以下のような Dockerfile を用意します。

FROM centos:7
## systemd
##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/*;
##VOLUME [ "/sys/fs/cgroup" ]
# yum install
RUN yum -y update && yum -y install \
    epel-release \
    sudo \
    less \
# network ss (instaed of netstat)
    iproute \
# ssh
    openssh-clients \
# apache
    httpd-devel
# move apache config
RUN mv -i /etc/httpd/conf.d/autoindex.conf /etc/httpd/conf.d/autoindex.conf.org && \
    mv -i /etc/httpd/conf.d/userdir.conf /etc/httpd/conf.d/userdir.conf.org && \
    mv -i /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.org
# add last
RUN echo ServerName www.example.com:80 >> /etc/httpd/conf/httpd.conf
RUN echo ServerTokens Prod >> /etc/httpd/conf/httpd.conf

# # httpd service
RUN systemctl enable httpd.service
RUN systemctl start httpd.service
CMD ["/sbin/init"]
EXPOSE 80

## CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
#EXPOSE 80
#CMD /usr/sbin/httpd -DFOREGROUND

# volume directory
RUN mkdir /workspace

docekr-compose.yml

続いて docekr-compose.yml

version: '3.8'
services:
  elephant:
    build: .
    volumes:
      - ./workspace:/workspace
#      - /sys/fs/cgroup:/sys/fs/cgroup:ro
    tty: true
    ports:
       - "8080:80"
    entrypoint: bash -c "bash /workspace/entrypoint.sh && /bin/bash"
    privileged: true

/workspace/entrypoint.sh はブランクで。

検索して引っかかった記事ではこのようなやり方で上手く行った、というのがいくつか見受けられたのですが、今回は上手く行かず……。

参考

Failed to get D-Bus connection: Operation not permitted

シェルの処理

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/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]

これを Dockerfile に入れてもダメでした。

systemctl を使用しないやり方

この方法も試しましたがダメでした。

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。