amazon

[Docker]Ubuntu + Apache + Laravel 環境を構築する

はじめに

AWS EC2 上に Apache + Laravel で Web2層構成で構築を考えており、構築手順の確認等を含めて Docker 上で再現しました。その過程でいくつかはまったポイントを記載します

環境

  • ホストマシン
    • WSL2
    • Docker 20.10.12
  • コンテナ
    • OS Ubuntu 20.04
    • php 7.4.3
    • Nodejs 16.17.0
    • npm 8.15.0
    • composer 2.4.1
    • Laravel 8.83.23

まず動く Dockerfile を 以下に記載します。

Dockerfile

FROM ubuntu:20.04

# Configuring tzdata settings
ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # --A--

# install git, vim, curl, apatche, php7.x, node, npm, composer
RUN apt-get update && \
  apt-get install git vim curl \
  apache2 \
  php libapache2-mod-php php-mbstring php-cli php-bcmath php-json php-xml php-zip php-pdo php-common php-tokenizer php-mysql php-curl php-gd php-soap php-xmlrpc \
  nodejs \
  npm -y && \
  curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \ # --B--
  npm install n -g && n stable && apt purge -y nodejs npm # --C--

# apatche Pass of AH00558
RUN echo "ServerName localhost" | tee /etc/apache2/conf-available/fqdn.conf && a2enconf fqdn && a2enmod rewrite # --D--

WORKDIR /var/www/html
EXPOSE 80
CMD ["apachectl", "-D", "FOREGROUND"] # --E--

ポイント

–A– タイムゾーンの設定

tzdata を install する際、以下のようにタイムゾーン選択を求められ、Image 作成が停止してしまいます。

ex) tzdata インストール時のログサンプル
Configuring tzdata
------------------

Please select the geographic area in which you live. Subsequent configuration
questions will narrow this down by presenting a list of cities, representing
the time zones in which they are located.

  1. Africa      4. Australia  7. Atlantic  10. Pacific  13. Etc
  2. America     5. Arctic     8. Europe    11. SystemV
  3. Antarctica  6. Asia       9. Indian    12. US
Geographic area:

これを回避するためにあらかじめタイムゾーンを設定しておく必要があります。東京にするために以下の設定を Dockerfile に加えます。

NV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezon
–B– 最新 composer のインストール

Ubuntu 20.04 のリポジトリの composer は 1系のため、composer install が異様に遅い[1]です。
高速化プラグインを入れてもよいのですが、1系に対応していないライブラリもあるので以下の設定で最新の composer インストールを Dockerfile に加えます。

当初1系で composer install したら30分経っても終わりませんでした。

curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
–C– nodejs, npm バージョンの最新化

Laravel Mix[2] でフロントリソースのコンパイルを行うために最新化します、Ubuntu の標準ライブラリでは Nodejs 10系ですが、 Laravel 8.x は Nodejs12以上を求められます。
最新版にするために以下の設定を Dockerfile に加えます。

apt-get install nodejs npm
npm install n -g && n stable && apt purge -y nodejs npm
–D– Apache サーバ名エラーの解決

サーバ名が解決できない場合以下のエラーが発生しました。

AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.168.3.10. Set the 'ServerName' directive globally to suppress this message

default.conf で serverName を localhost としているのでこちらも同じようにするため、以下の設定を Dockerfile に加えます。

echo "ServerName localhost" | tee /etc/apache2/conf-available/fqdn.conf && a2enconf fqdn
–D– Apache で Laravel Top ページ以外も読めるようにする

Laravel で routes とページを追加した[2]のに ルート「/」以外 404 not found で表示できない事象がありました。以下に route:list を見た場合のログを表示します。

 php artisan route:list
+--------+----------+---------------------+------+------------------------------------------------------------+------------------------------------------+
| Domain | Method   | URI                 | Name | Action                                                     | Middleware                               |
+--------+----------+---------------------+------+------------------------------------------------------------+------------------------------------------+
|        | GET|HEAD | /                   |      | Closure                                                    | web                                      |
|        | GET|HEAD | api/user            |      | Closure                                                    | api                                      |
|        |          |                     |      |                                                            | App\Http\Middleware\Authenticate:sanctum |
|        | GET|HEAD | buzz_tube           |      | Closure                                                    | web                                      |
|        | GET|HEAD | sanctum/csrf-cookie |      | Laravel\Sanctum\Http\Controllers\CsrfCookieController@show | web                                      |
+--------+----------+---------------------+------+------------------------------------------------------------+------------------------------------------+

Laravel は public/.htaccess の値を読み込んでリダイレクトすることで URL に遷移します。Apache の mod_rewite[3] というモジュールが使えないとリダイレクトができず、 Laravel でルーティングができず、使えないということになります。
mod_rewite を使えるようにするために以下の設定を Dockerfile に加えます。

a2enmod rewrite
–E– Apache サーバの起動

docker run でコンテナを動かしたら Apache が起動し、ポート番号80でアクセスできるように以下の設定を Dockerfile に加えます。

EXPOSE 80
CMD ["apachectl", "-D", "FOREGROUND"]

docker-compose.yml

version: '3.8'

services:
  php:
    container_name: php
    build:
      context: ./php
    ports:
      - '8080:80'
    volumes:
      - ../src:/var/www/html
      - ./apache/default.conf:/etc/apache2/sites-enabled/000-default.conf

Apache の公開ディレクトリに Laravel のプロダクトルートを設定し、 Apache の conf ファイルを指定したファイルにします。

default.conf

<VirtualHost *:80>
   ServerName localhost
   DocumentRoot /var/www/html/public

   <Directory /var/www/html>
      AllowOverride All
   </Directory>
   ErrorLog ${APACHE_LOG_DIR}/error.log
   CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

公開ディレクトリのサブディレクトリも読み込めるように AllowOverride を ALL にします

嵌った点

composer が遅い

当初、 apt install composer で入れていたため、1系を使用していました。30分待っても終わらないとかで3,4時間無駄にしたことになりました。
遅い要因は主に3つある[4]ようです。

  • packagist.orgが日本から遠い
  • composerのアーキテクチャ的に、小さなjsonファイルを少しずつダウンロードするため、ネットワークの遅延がもろに影響する
  • composerがfile_get_contentsでjsonをダウンロードしていて、どうやらKeep-Aliveを使っていないし、並列ダウンロードもしていない

速くする方法は3つあり、今後のバージョンアップを考えて最新版にしました。
方法の3つを以下に示します。今回採用しない方針では1系しか対応していないので2系を求められるライブラリを使いたい場合に詰みます。

  • 2系にする
  • 日本にある非公式ミラーを使う
  • 高速化プラグインを入れる

トップページ以外 404になる

Laravel の route:list が正しく表示されていたので Apache カラミだと思っていましたが凡ミスではまっていました。「a2enmod rewrite」にはたどり着いていたのですが、別コンテナで動かしており、うまくいかないと悩んでいました。

サーバは 「docker compose up」で動かして、「a2enmod rewrite」を叩いたのは 「docker compose run –rm php bash」だったので別コンテナで動かしていたといううっかりがありました。

まとめ

いろいろ悪戦苦闘しましたが、ひとまず Laravel プロジェクトを作成し、新しいページの作成&表示ができるようになりました。

php-apache[5] のようなインフラ周りをやってくれているイメージとかを使うことが多いのですが、できるだけ実際と同じ環境で構築していくのもミドルウェアやインフラ周りの不明点を明らかにできるので良いですね。

参考

[1] Composerの実行速度が遅い, https://qiita.com/FattyRabbit/items/9b5f9a84eea1df054b0a
[2] Add Youtube page #1, https://github.com/turkey136/buzz_day/pull/1/files#diff-97834c4cd54300b04a6c52ee47d862985b78d90cb2fe3b7662b1208f2fc21afd
[3] Apache Module mod_rewrite, https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
[4] 【PHP】たった1行コマンドを入力するだけでComposerを劇的に速くする方法【アジア圏限定】, https://yuzurus.hatenablog.jp/entry/composer-hayai
[5] php:8.1.10-apache, https://hub.docker.com/layers/library/php/8.1.10-apache/images/sha256-f399c48032f480495d94ce9327cd3bc03c87c38bf2a58ece04dd769fddabb0bf?context=explore

コメント

タイトルとURLをコピーしました