【失敗談】Apacheのコンテナが立ち上がらないエラー解決
EC2インスタンス内のhttpd.confをDocker環境でそのまま使おうとしてエラーになりました。
以下のようにローカルの./apache/conf.d/httpd.conf
をコンテナの/usr/local/apache2/conf/httpd.conf
にボリュームマウントしました。
volumes:
- ./apache/conf.d/httpd.conf:/usr/local/apache2/conf/httpd.conf
ローカルのhttpd.conf
には、EC2のhttpd.conf
をそのままコピーして貼り付けました。
その状態でdocker compose up -d --build
を実行すると、以下のエラーが出ました。
httpd: Syntax error on line 34 of /usr/local/apache2/conf/httpd.conf: ServerRoot must be a valid directory
/usr/local/apache2/conf/httpd.conf
はコンテナ内のhttpd.conf
です。その34行目で間違いが指摘されています。
docker exec -it [コンテナID] bash
でログインして見に行こうとしましたが、コンテナが動いていないので拒否されました。
Error response from daemon: Container 2e60e217d98bd88d7fa1b03d74229893b317f406fc1836a39282e59b1d9765a4 is not running
そんなときはdocker run --entrypoint
で、動いていないコンテナに入ることができます。
docker run -it --entrypoint /bin/bash -v $(pwd)/apache/conf.d/httpd.conf:/usr/local/apache2/conf/httpd.conf httpd:latest
エントリーポイントとは、Dockerが起動する際のメインのコマンドやプロセスのことです。
デフォルトの設定では、ApacheコンテナのエントリーポイントはCMD ["httpd-foreground"]
です。
それをdocker run -it --entrypoint /bin/bash
で一時的にbashに上書きしています。
Apacheコンテナに入って/usr/local/apache2/conf/httpd.conf
を確認すると、指摘されたのは以下の箇所でした。
ServerRoot "/etc/httpd"
ServerRoot
には、apache関連ファイルの最上位のディレクトリ(要はApacheがある場所)を指定する必要があります。
EC2ではApacheは/etc/httpd
にあったのですが、Dockerコンテナでは/usr/local/apache2
にあります。
# EC2
ServerRoot "/etc/httpd"
# Dockerコンテナ
ServerRoot "/usr/local/apache2"
httpd: Syntax error on line 61 of /usr/local/apache2/conf/httpd.conf: Include/IncludeOptional: Could not open directory /usr/local/apache2/conf.modules.d: No such file or directory
コンテナのhttpd.conf
にInclude conf.modules.d/*.conf
があり、モジュール設定ファイルの読み込みに失敗しています。
/usr/local/apache2/conf.modules.d
を探しに行って「そんなファイルはないよ」と言われています。
実際確認してみると、確かにありませんでした。
root@434977c744b1:/usr/local/apache2/conf# ls
extra httpd.conf magic mime.types original
EC2のほうで確認するとありました。conf.modules.d
の中には複数の設定ファイルがあり、そこでさまざまなモジュールがあります。
[user@ip-10-0-0-13 httpd]$ ls
conf conf.d conf.modules.d logs modules run state
[user@ip-10-0-0-13 conf.modules.d]$ ls
00-base.conf 00-dav.conf 00-mpm.conf 00-proxy.conf 01-cgi.conf 10-proxy_h2.conf
00-brotli.conf 00-lua.conf 00-optional.conf 00-systemd.conf 10-h2.conf README
Dockerコンテナでは、/usr/local/apache2/modules
下にモジュールがあります。
これらのモジュールを使えるようにするため、Include /usr/local/apache2/modules
としてみます。
これによって次のエラーが生じました。
httpd: Syntax error on line 62 of /usr/local/apache2/conf/httpd.conf: Syntax error on line 453 of /usr/local/apache2/modules/mod_access_compat.so: /usr/local/apache2/modules/mod_access_compat.so:453: <\x14> was not closed.
mod_access_compat.so
の中身を見てみると、人は読めないコードでした。
mod_access_compat.so
のエラー解決だけでも難しく、これを解決したとしても他のモジュールでもエラーが生じ、キリがなくなりそうだと思いました。
ここで私が考えたことは以下2つです。
- モジュールを使えるようにする設定が間違っているのではないか?
- EC2の設定ファイルの内容を丸ごとボリュームマウントするから様々なエラーが出てしまうのではないか?
いったんボリュームマウントをコメントアウトしてdocker compose up
してみると、Apacheコンテナが正常に起動されました。
Apacheコンテナにログインして/usr/local/apache2/conf/httpd.conf
を確認してみると、ServerRoot
やaccess_compat_module
が正しく設定されていました。
ServerRoot "/usr/local/apache2"
LoadModule access_compat_module modules/mod_access_compat.so
ここまでの確認で、1.はわかりませんが、2.の予想は正しそうです。
EC2のhttpd.conf
とDockerのhttpd.conf
は違いがあるので、EC2のhttpd.conf
でコンテナ内にボリュームマウントしないほうがよいですね。
そもそもなぜボリュームマウントしようとしたかというと、リバースプロキシの設定をするためでした。
EC2では、以下のようにApacheをリバースプロキシ化する設定を行いました。
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
ProxyRequests Off
ProxyPass / http://0.0.0.0:3000/
ProxyPassReverse / http://0.0.0.0:3000/
丸ごと上書きするのではなく、リバースプロキシの部分だけ追加すべきでした。
コンテナ内のhttpd.conf
を確認したところ、デフォルトでproxy_module
とproxy_http_module
があったので、ProxyRequests
ProxyPass
ProxyPassReverse
だけ追加すればよさそうです。
docker compose up -d --build
を実行する時に、apacheコンテナをhttpd-foreground
で実行する前に、/usr/local/apache2/conf/httpd.conf
に以下3行を追加します。(rails
はdocker-composeのサービス名での指定です)
3行追加する用のシェルスクリプトを作成し、docker-compose.yaml
のなかのApacheサービスのcommand
で実行させました。
#!/bin/sh
echo 'ProxyRequests Off' >> /usr/local/apache2/conf/httpd.conf
echo 'ProxyPass / http://rails:3000/' >> /usr/local/apache2/conf/httpd.conf
echo 'ProxyPassReverse / http://rails:3000/' >> /usr/local/apache2/conf/httpd.conf
httpd-foreground
services:
apache:
image: httpd:latest
ports:
- :80:80
volumes:
- ./apache/conf.d/start-apache.sh:/usr/local/bin/start-apache.sh
depends_on:
- rails
command: /usr/local/bin/start-apache.sh
しかしこの方法はうまくいきませんでした。次のエラーが出ました。
AH00526: Syntax error on line 552 of /usr/local/apache2/conf/httpd.conf:Invalid command 'ProxyRequests', perhaps misspelled or defined by a module not included in the server configuration
なんでproxy_module
とproxy_http_module
が存在するのにエラーになるのだろう?と思ってhttpd.conf
をよく見ると、どっちもコメントアウトになっていました。
わざわざコマンドでコメントアウトを削除するのも面倒ですし、コメントアウトとはいえ存在するのに追加して重複になるのも避けるべきと考えました。
そのため、結局何もしないでdocker compose up
で起動して、Apacheコンテナが起動した状態でhttpd.conf
をcat
コマンドで表示させて、それをローカルのhttpd.conf
にコピペして、そこにさっきの5行を追加しました。(コメントアウトの2行は削除して)
最終的にdocker-compose.yaml
は以下となりました。
当初のボリュームマウントはEC2の内容をコンテナに反映していましたが、下のはリバースプロキシ部分を適用するためです。
version: '3'
services:
apache:
image: httpd:latest
ports:
- :80:80
volumes:
- ./apache/conf.d/httpd.conf:/usr/local/apache2/conf/httpd.conf
depends_on:
- rails
command: httpd-foreground
rails:
build: .
command: rails s -b 0.0.0.0
ports:
- 3000:3000
volumes:
- .:/ocr_check_app
個人的にいちばんの学びはdocker run --entrypoint
で、動いてないコンテナに入ってファイルを確認できるところです。
Discussion