DockerとLaravelを使って開発してみよう
読む所要時間: 18 分
あなたが所属する開発チームは最近アプリをリリースし、そのアプリが短期間で大ヒットしていることが分かりました。利用者からの需要は収まらず、開発チームは「スケールアップ」について検討を始めました。
かつて、このスケールアップ作業は「垂直スケーリング」と呼ばれ、高機能のサーバーに投資することを意味していましたが、最近のコンテナ技術の台頭により、低コストで迅速にコンテナを追加できるようになり、アプリケーションの水平スケーリングが可能になりました。
これにより、2つの大きなメリットがもたらされます。1つ目は、高機能のサーバーに追加コストをかける必要がないことです。2つ目は、現在の顧客の需要に基づいて、アプリケーションのスケールアップとスケールダウンが可能になることです。
本稿では、LaravelプロジェクトでDockerを使用する方法について紹介します。Dockerを使えば、アプリケーションの使用量の急増と急減の両方に対応してスケーリング可能なアプリケーションを開発できます。
以下のチュートリアルでは、ApacheをWebサーバーとして使用し、PostgreSQLでデータベースエンジンを提供します。著名な歴史家による有名な名言を表示するアプリケーションを作成します。
必要条件
このチュートリアルを進めるには、以下の項目が必要です。
- PHPとLaravelの基本的な知識。
- コンテナ、イメージ、ネットワーク、サービスなど、基本的なDocker用語の知識。Jeff Hale氏は、これらの用語について、連載記事で分かりやすく解説しています。これらの用語についてあまり知らない場合は、ぜひ読んでみてください。
- Docker Desktop
はじめに
最初に、laravel_docker
という名前の新しいディレクトリを作成します。
このアプリケーションは、相互に通信する必要のあるさまざまなコンポーネントで構成されているため、Docker Composeを使用してサービスを定義します。laravel_dockerディレクトリのルートに、docker-compose.ymlという名前の新しいファイルを作成します。
このファイルには、コンテナのビルド方法から、コンテナにアクセス可能なネットワークやボリュームまで、アプリケーションの設定で作成するコンテナのすべての設定が保持されます。
docker-compose.ymlに以下を追加します。
version
はスキーマバージョンを参照し、services
は、アプリケーションスタックを構成するコンテナのリストを定義します。services
は、実際は単なる「本番環境のコンテナ」です。
次の各セクションでは、データベース、Apache Webサーバー、PHPのコンテナについて説明します。
データベースコンテナをビルドする
docker-compose.ymlで、services
エントリを次のように更新します。
container_name
は、Docker Composeでコンテナを自動的に生成するのではなく、実行時にコンテナの名前を設定します。
image
は、コンテナのビルド元のブループリントをDockerに認識させることができます。今回は、データベースエンジンとしてPostgreSQLを使用するため、postgres
を指定します。
environment
キーは、デフォルトのデータベースの名前やパスワードなど、環境変数のリストを指定します。ここでは、ユーザー名を指定していないため、データベースのユーザー名は「postgres」になります。
ports
キーを使用して、ローカル開発マシンのポートをコンテナのポートにマップし、GUIツールを使用してデータベースに接続できるようにします。コロン(:
)の左側に指定されているポートは、コンピューターのポートです。右側に指定されているポートは、コンテナのポートです。
次に、volume
キーを使用してボリュームを宣言します。Docker公式ドキュメントによると:
ボリュームは、Dockerコンテナが生成、使用するデータを保持するための推奨メカニズムです。
コンテナの破棄または再ビルド時にデータベースが失われないようにするために、ボリュームを宣言します。
PHPとApacheコンテナをビルドする
データベースコンテナとは異なり、PHP/Apacheコンテナを設定するには、追加の指示を指定する必要があります。これを行うには、DockerfileからPHPコンテナをビルドします。ルートディレクトリlaravel_dockerに、phpという名前のディレクトリを作成します。次に、laravel_docker/phpに、Dockerfileという名前のファイルを作成します。
laravel_docker/php/Dockerfileに、以下を追加します。
公式のPHP Dockerイメージには、Apacheサーバーに付属するバリエーションが用意されています。これをFROM
で指定すると、ベースコンテナにApacheがインストールされます。
PHPイメージからコンテナのための骨組みを作成することに加えて、以下を実行します。
- Laravelが依存するPHP拡張機能をインストールします。
- コンテナの作業ディレクトリを/var/www/laravel_dockerに設定します。
- Composerをインストールします。
次に、docker-compose.ymlを次のように更新します。
php-apache
コンテナは、docker-compose.ymlにdatabase
コンテナとは異なる定義にします。イメージを指定する代わりに、ビルドコンテキストを指定します。このように、docker-compose
コマンドを実行すると、phpディレクトリに宣言されたDockerfileがコンテナのビルドに使用されます。
次に、データベースコンテナの場合と同様に、ローカル開発マシンのポート8080がコンテナのポート80にマップされます。./apache/default.confに指定された仮想ホストの設定はこのポートでリッスン(待機)するため、ポート80が使用されます。
コンテナで生成されたデータを保持するため、ボリュームを宣言します。この場合、Laravelアプリケーションはphp-apache
コンテナの/var/www/laravel_dockerディレクトリに作成されます。ただし、これはローカル開発マシンのプロジェクトディレクトリのsrcディレクトリに保持されます。
Apacheによりデフォルトで有効化されている000-default.conf
ホストとアプリケーションの仮想ホストの設定をリンクできるように、追加のボリュームが宣言されています。これまでは、デフォルトの設定を無効にしてから独自の設定を有効にし、コンテナがビルドまたは再ビルドされるたびにApacheサーバーをリロードする必要がありましたが、これにより、そのストレスが軽減されます。
その後、新しい設定キー(depends_on
)を導入します。これにより、php-apache
コンテナの前にまずデータベースコンテナをビルドする必要があることをDockerに認識させることができます。
プロジェクトのルートディレクトリにsrcディレクトリを作成します。
php-apache
コンテナからLaravelプロジェクトをスキャフォールドすると、プロジェクトファイルがここに保持されます。次に、apache
という名前のディレクトリを作成します。その中に、default.confというファイルを作成します。
以下をapache/default.confに追加します。
これで、ようやくコンテナをビルドできます。次のコマンドを実行します。
Docker Desktopアプリケーションを開くと、次のスクリーンショットで示すように、新しく作成されたコンテナが表示されます。
Laravelアプリケーションを設定する
Laravelアプリケーションを設定するには、次のコマンドを使用し、php-apache
コンテナでコンテナを開始します。
これにより、php-apache
コンテナでCLIが開きます。次のコマンドを使用し、Laravelアプリケーションを作成します。
完了後に、http://localhost:8080/に移動します。デフォルトのLaravelのウェルカムページが表示されます。
また、srcディレクトリを見ると、Laravelプロジェクトファイルもそこに追加されていることが分かります。
src/.envで、以下のようにデータベースパラメーターを編集します。
アプリケーションを構築する
本稿では名言アプリケーションを作成します。まずはアプリケーションのモデルを作成してみましょう。php-apache
コンテナで、次のコマンドを実行します。
-f
引数により、名言のファクトリーを作成することをartisanに認識させることができます。同様に、-m
は移行用、-s
はデータベースシーダー用です。
src/database/migrations/YYYY_MM_DD_HHMMSS_create_quotes_table.phpで、以下のようにup
関数を更新します。
次に、src/database/seeders/QuoteSeeder.phpを開き、run
関数に以下を追加します。
これにより、QuoteFactoryから名言が50回作成され、毎回データベースに保存されます。
注:次のインポートを追加することを忘れないでください:
src/database/seeders/DatabaseSeeder.phpで、run
関数に以下を追加します。
これにより、db:seed
コマンドが実行されたときにQuoteSeeder
が実行されます。次に、src/database/factories/QuoteFactory.phpで、definition
関数に以下を追加します。
移行を実行してデータベースをシードするには、php-apache
コンテナで次のコマンドを実行します。
データベースに何が追加されたかを確認するには、次のコマンドを実行し、データベースコンテナへのコマンドラインを開きます。
次に、次のコマンドを実行し、PostgreSQLサービスにログインします。
SQLクエリを実行し、名言テーブルのすべての項目を取得します。
次のスクリーンショットのように出力されます。
準備ができたら、次のコマンドを使用して名言のリクエストを処理するコントローラーを作成します。
src/app/Http/Controllers/QuoteController.phpを開き、以下のように更新します。
index
関数では、データベースからすべての名言を取得し、ビュー(quotes/index.blade.php)に渡して、名言を表示します。現時点ではビューが存在しないため、次のコマンドを実行してビューを作成します。
src/resources/views/quotes/index.blade.phpを開き、以下を追加します。
このテンプレートでは、Bootstrapを使用して名言テーブルのスタイルを設定します。次に、foreach loopディレクティブを使用して、QuoteController
から受信した名言をループ処理し、名言、歴史家、年をそれぞれ表示します。
最後に、ルーティングを更新し、インデックスページに名言を読み込みます。これを行うには、src/routes/web.phpを開き、以下に一致するようにルート宣言を更新します。
これにより、index
ページにアクセスしたときに、ウェルカムページを返す代わりに、QuoteController
のindex
関数が呼び出されます。
変更をテストする
変更をテストするには、http://localhost:8080/に移動します。次のスクリーンショットのようなページレンダリングが表示されます。
すべて破棄する
先程、docker-compose up -d –build
コマンドを使用して、コンテナを作成してビルドしました。ハードディスクの空き容量が少ない、アプリケーションが冗長であるなどの理由で、システムのクリーンアップが必要になる場合がありますが、Dockerでは、このための機能がすでに用意されています。コンテナと関連するすべてのネットワークを停止して削除するには、次のコマンドを実行します。
次のように出力されます。
アプリケーションをスケーリングする
サービスの1つのインスタンスでは、アプリケーションへのすべてのトラフィックを十分に処理できない場合があります。このような場合に対応できるように、Dockerでは、–scale
フラグを使用したサービスのスケーリング(サービスの複数のインスタンスの作成)をサポートしています。
たとえば、php-apach
eサービスをスケールアップするには、docker-compose.ymlを開きます。ここでは、2つの変更を行います。最初に、コンテナ名の設定を削除します。これは、コンテナ名が一意である必要があるためです。同じ名前で複数のサービスを作成しようとすると、Dockerはエラーを出力します。
同様に、サービスのポート設定を変更します。これにより、新しく作成された各サービスにDockerがポートを自動的に割り当てることができます。コンテナ名と同様に、2つのサービスを同じポートにバインドすることはできません。
これらの変更を行うには、以下のようにphp-apache
サービス設定を更新します。
設定の更新後に、次のコマンドを実行し、php-apache
サービスのインスタンスを10個作成します。
これが完了すると、次のスクリーンショットのような出力がターミナルに表示されます。
すべてが機能していることをテストするには、docker-compose ps
を実行します。次の例のような出力が表示されるはずです。
DockerとLaravelの使用を開始する方法は以上です
イメージとDockerfileからコンテナをビルドできるだけでなく、コンテナを相互に通信させることもできるため、Laravelアプリケーションとデータベースを個別のコンテナで実行できます。
これは、水平スケーリングが可能なアプリケーションスタックを作成するための第一歩です。コンテナオーケストレーションのインフラストラクチャを使用することにより、サーバーで処理されるリクエストの数に合わせてコンテナを作成および破棄できます。
このチュートリアルのコードベース全体は、GitHubで入手できます。ぜひご確認ください。コーディングを楽しみましょう!
Oluyemiは、電気通信工学のバックグラウンドを持つテクノロジー愛好家です。ユーザーが直面する日々の問題を解決することに強い関心を持ち、プログラミングの道に進んで以来、Webとモバイルの両方のソフトウェア開発で問題解決能力を磨いてきました。
Oluyemiは、知識の共有に情熱を注ぐフルスタックのソフトウェアエンジニアであり、ブログで多数の技術記事とコンテンツをインターネットに公開しています。テクノロジーにも精通しており、趣味は新しいプログラミング言語とフレームワークを試すことです。
- Twitter: https://twitter.com/yemiwebby
- GitHub: https://github.com/yemiwebby
- Webサイト: https://yemiwebby.com.ng/