Laravel x Dockerで開発・本番環境を構築する① 最小構成編

開発/プログラミング

こんにちは!アライグマ先生です!

皆さんはLaravelで開発する時はどのような構成にしていますか?

今回は開発環境でもDocker、本番環境でもDockerを使用してLaravelを動かしてみる記事を書いてみます。

Laravelをコンテナ上で動かす手法としては様々ありますが、今回はシンプルにDockerを使って動かせるように構築していきます。

最終的に目指したい全体図は以下の画像のような感じです。

しかし、一度に全体を説明すると分からなくなってしまいがちです。そのため、今回は以下のように内容を分けたいと思います。

  1. 最小構成編
  2. DB編
  3. パフォーマンスチューニング・運用編

Dockerを使って開発・運用する目的

今回作成するサンプルは以下の目的でDockerを使用します。

  • インフラ構築の再現性
  • コードに落とし込むことで手順書になる
  • チーム開発がしやすい
  • スケールしやすい

「Dockerさえあれば全てコンテナ内で開発することで自分のPCをクリーンな状態に保てる!」ということは目的としていないです。

「技術を使うことで得られる便利さ」と「手間」を天秤にかけて、この辺りが一番コスパいいんじゃないかな~と思っています。

そのため、開発するPCにはPHPとComposer、Dockerが動く環境を用意する必要があります。

使用する主な技術とバージョン

  • PHP 8.2
  • Laravel 10
  • Docker
  • Apache2

実際にやっていく

Laravelプロジェクトの作成

初めにLaravelプロジェクトを作成します。

CLI
$ composer create-project laravel/laravel laravel-docker-sample

初期のディレクトリは以下の画像のような感じになります。

動作確認のためにバージョンを確認しておきます。

CLI
$ php artisan -V
Laravel Framework 10.30.1

ここまで動いたら念のためデフォルトで動くサーバーを起動してみます。

CLI
$ php artisan serve                                   

   INFO  Server running on http://127.0.0.1:8000.

立ち上がったサーバー(http://localhost:8000)にアクセスすると初期ページが見れました!

Docker上でLaravelを動かす

ローカルで動くことが確認できたので、次にDocker上で動くようにしてみます。

Dockerfileをプロジェクトのディレクトリに作成し、DockerfileにLaravelを動かすためにComposerとPHPを使うように記述します。

CLI
$ touch Dockerfile
Dockerfile
FROM composer as build
WORKDIR /app
COPY . /app
RUN composer install

FROM php:8.2-fpm
WORKDIR /app
EXPOSE 8000

COPY --from=build /app /app

CMD ["php", "artisan", "serve", "--host", "0.0.0.0"]

記述できたら、プロジェクトのルートディレクトリで以下のコマンドを入力します。

CLI
$ docker build -t app .
$ docker run -p 8000:8000 app

   INFO  Server running on http://0.0.0.0:8000.

http://0.0.0.0:8000とありますが、これはDocker内で受け付けているサーバーのアドレスなので、開発PCからアクセスするときはhttp://localhost:8000にアクセスします。

すると先程と同じように初期ページを見ることが出来ました!これでDocker上でLaravelが動くようになりました!

Webサーバーを導入する

開発用の場合はこれで良いんですが、本番で運用するには向いていません。

php artisan serveは内部的にPHPに組み込まれた簡易的なサーバーが使われており、本番用には向いていないためです。

詳しく知りたい方は以下のブログで疑問を解消しつつ解説してくださっているのでオススメです。

Laravel を Docker で動かしてホスティングするまで
ひょんとしたことから PHP をやることになったのですが、Laravel を コンテナでホスティングするのが難しすぎて困っています。とりあえず今できていることをメモです。こうした方が良いよ的なアドバイスがあったら教えて欲しいです。 ちなみに本当は昨日公開予定のブログでしたが、X…

そのため、Apacheを導入します。

まず、Apacheの設定ファイルを作成します。

CLI
$ mkdir build
$ touch build/000-default.conf
build/000-default.conf
<VirtualHost *:8000>

  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/public/

  <Directory /var/www/>
    AllowOverride All
    Require all granted
  </Directory>

  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

そして、Dockerfileを変更します。

Dockerfile
FROM composer as build
WORKDIR /app
COPY . /app
RUN composer install

FROM php:8.2-apache
WORKDIR /var/www/
EXPOSE 8000

COPY --from=build /app /var/www/
COPY ./build/000-default.conf /etc/apache2/sites-available/000-default.conf
RUN chmod 777 -R /var/www/storage/ && \
    echo "Listen 8000" >> /etc/apache2/ports.conf && \
    a2enmod rewrite

PHPのイメージもApache + PHPで動くようなイメージに変更しています。そして、先程書いた設定ファイルをコンテナ内の適切な場所(Apacheが設定を読み取る場所)にコピーしています。

Dockerfile
RUN chmod 777 -R /var/www/storage/ && \
    echo "Listen 8000" >> /etc/apache2/ports.conf && \
    a2enmod rewrite

上記の記述に関しては、以下のことを行っています。

  • chmodでLaravelがキャッシュやらログを吐き出す時に使うのでそのために権限を付与している
  • Apacheのポート設定
  • a2enmod rewrite でApacheのリライトモジュールを有効にしている(public/.htaccessでRewriteを使用しているので、これがないと正常に動かない)

Dockerfileなどがプロジェクトの内容が変わっているため再度コンテナを立ち上げます。

CLI
$ docker build -t app .
$ docker run -p 8000:8000 app

   INFO  Server running on http://0.0.0.0:8000.

同様にhttp://localhost:8000にアクセスして、レスポンスヘッダーを見ると、Apacheからの応答ということが分かります!

docker-composeを使う

この状態であれば、GCPのCloud Runなど、コンテナが動く環境にビルドしたイメージをデプロイすれば動くかなと思います。

しかし、セキュリティ的にも外部から柔軟に変更させたいので、コンテナの中にenvファイルを含めたくありません。また、変更が反映するために毎回ビルドするのが面倒なので、開発環境ではdocker-composeを使って快適に開発していきます。

docker-compose.yamlファイルと.dockerignoreファイルを作成します。

CLI
touch {docker-compose.yaml,.dockerignore}
docker-compose.yaml
version: "3"
services:
  app:
    build: .
    container_name: laravel-docker-sample
    ports:
      - "8000:8000"
    volumes:
      - .:/var/www
    env_file:
      - .env

.dockerignoreは.gitignoreと意味的にもほぼ一緒なのでコピーしてきます。

.dockerignore
/.phpunit.cache
/node_modules
/public/build
/public/hot
/public/storage
/storage/*.key
/vendor
.env
.env.backup
.env.production
.phpunit.result.cache
Homestead.json
Homestead.yaml
auth.json
npm-debug.log
yarn-error.log
/.fleet
/.idea
/.vscode

これで.envファイルがコンテナ内に入らないようになります。

しかし、.envの内容がアプリケーションの動作に必要なので、docker-composeで環境変数として外部から注入しています。

docker-compose.yaml
env_file:
  - .env

また、volumesを使うことで、ホスト側とコンテナ内を同期させることができます。そのため、即座に変更が反映され、再度ビルドしなくても良くなります。

docker-compose.yaml
volumes:
  - .:/var/www

このまま起動すると、storageの権限に関するエラーが起きます。ホスト側のstorageも権限を与えましょう。

CLI
$ chmod 777 -R ./storage/

最後にdocker composeを起動して終わりです。

CLI
$ docker compose up

welcome.blade.phpを変更して保存してみると、即座に反映されると思います!

終わりに

ここまで動けば後はアプリケーションを開発したり、設定を拡張していけば色んなことが出来るようになるかと思います。

次回はDB編を書こうと思っています。

お疲れさまでした!

コメント

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