Docker ComposeとSymfonyを使って開発してみよう
読む所要時間: 21 分
ソフトウェアをチーム間で開発すると、コードベースの管理や、開発者全員が問題なく使える開発環境の準備など、さまざまな困難が生じます。
Gitはバージョン管理において大きな役割を果たしており、誰もが問題なくコードベースを操作できるようになりましたが、作業環境が原因で混乱が生じるリスクがまだあります。
WindowsやmacOS、Linuxなど、開発者が好むオペレーティングシステムはさまざまであり、同じことがアプリケーションの導入環境にも当てはまります。
その結果、特定のエラーが発生すると、問題の原因を突き止めることが困難になります。エラーが1つのOSでのみ発生することが混乱に拍車をかける可能性もあります。開発者の間で有名なフレーズ、「It works on my machine」(私のマシンでは動作するのに)の状態につながります。
Dockerを開始する
小規模で軽量の実行環境であるコンテナにアプリケーションを作成することにより、アプリケーションの予測可能性が向上します。コンテナでは、基盤となるオペレーティングシステムカーネルを共有しますが、それ以外は互いから切り離して実行されます。
DockerをSymfonyプロジェクトに統合することにより、導入先に関係なく、アプリケーションの実行時に環境とその設定を常に同じにすることができます。
本稿では、SymfonyプロジェクトでDockerを使用する方法について紹介します。ここでは、NginxがWebサーバーとして使用され、PHP-FPMがPHPリクエストを処理し、MySQLがバックエンドデータベースになります。本稿では、著名な歴史家による有名な名言が表示されるアプリケーションを作成します。
必要条件
- Symfony、Twig、ORM(特にDoctrine)の経験。
- Dockerに関連する基本的な用語(コンテナ、イメージ、ネットワーク、サービス)の知識。Jeff Hale氏は、これらの用語について、連載記事で分かりやすく解説しています。これらの用語についてあまり知らない場合は、ぜひ読んでみてください。
- グローバルにインストールされているComposer。
- Docker Desktop
- Symfony CLIツール
はじめに
最初に、symfony_dockerという名前の新しいディレクトリを作成し、次のコマンドで、そのディレクトリに切り替えます。
Docker Composeの設定を作成する
アプリケーションを構成するさまざまなコンテナが通信する必要があるため、Docker Composeを使用し、それらを定義します。symfony_dockerディレクトリのルートで次のコマンドを使用し、docker-compose.ymlという名前の新しいファイルを作成します。
このファイルには、コンテナのビルド方法から、コンテナにアクセス可能なネットワークやボリュームまで、アプリケーションのスタックで作成するコンテナのすべての設定が保持されます。
docker-compose.ymlに以下の設定を追加します。
version
はスキーマバージョンを参照します。services
は、アプリケーションスタックを構成するコンテナのリストを定義します。services
は、実際は単なる「本番環境のコンテナ」です。
次の各セクションでは、MySQLデータベース、PHP、Nginx Webサーバーのコンテナについて説明します。
データベースコンテナを定義する
データベースコンテナを定義するには、docker-compose.ymlで、次のように services
要素を更新します。
container_name
では、Docker Composeでコンテナを生成するのではなく、実行時にコンテナの実際の名前を設定します。
image
では、コンテナのビルド元のイメージ(ブループリント)をDockerに認識させることができます。この場合、バージョン8のMySQLを使用するため、mysql:8.0
を指定します。
command
では、ユーザーの認証にMySQLで使用される認証プラグインを指定します。environment
キーを使用すると、データベースの名前、ユーザー、パスワード、ルートユーザーのパスワードなどの環境変数を指定できます。
データベースに接続するポートも必要です。ports
キーを使用して、ローカル開発マシンのポートを指定し、データベース接続の処理に使用されるコンテナのポートにマップします。
最後に、volumes
キーを使用してボリュームを宣言します。Docker公式ドキュメントによると:
ボリュームは、Dockerコンテナが生成、使用するデータを保持するための推奨メカニズムです。
コンテナの破棄または再ビルド時にデータベースが失われないようにするために、ボリュームを宣言します。
PHPコンテナを定義する
データベースコンテナとは異なり、PHPコンテナを設定するには、追加の指示を指定する必要があります。これを行うには、DockerfileからPHPコンテナをビルドします。ルートディレクトリsymfony_dockerに、phpという名前のディレクトリを作成します。次に、symfony_docker/phpに、Dockerfileという名前のファイルを作成します。
続いて、symfony_docker/php/Dockerfileに、以下を追加します。
PHP-FPMイメージからコンテナの雛形を作成することに加えて、以下を実行します。
- Symfonyが依存するPHP拡張機能をインストールします。
- コンテナの作業ディレクトリを/var/www/symfony_dockerに設定します。
- Composerをインストールします。
- Symfony CLIをインストールします。
次に、データベース設定の後に、以下のサンプルをdocker-compose.ymlに追加します。
ご覧のとおり、PHPコンテナは異なる方法で定義されています。イメージを指定する代わりに、ビルドコンテキストを指定します。このように、docker-compose
コマンドを実行すると、php/Dockerfileに宣言された指示がコンテナのビルドに使用されます。
コンピューターのポート9000
は、コンピューターのポートをMySQLデータベースのコンテナのポートにマップしたのと同じように、コンテナのポート9000
にマップされます。
さらに、この場合もボリュームを宣言します。これは、コンテナで生成されたデータを保持するためです。この場合、SymfonyアプリケーションはPHPコンテナの/var/www/symfony_dockerディレクトリに作成され、プロジェクトのappディレクトリに保持されます。
最後に、depends_on
キーを使用します。PHPとデータベースコンテナの間に依存関係が作成されることにより、PHPコンテナの前にデータベースコンテナをビルドして開始するようにDockerに指示されます。
PHPコンテナを定義し、次のコマンドを使用して、プロジェクトのルートディレクトリにappディレクトリを作成します。これはコンテナで必要になります。
Nginxコンテナを定義する
Nginxコンテナをビルドする前に、サーバーのデフォルト設定を記述しましょう。プロジェクトのルートに、nginxという名前のディレクトリを作成し、その中に、次のコマンドを使用して、default.confという名前の設定ファイルを作成します。
以下の設定をnginx/default.confに追加します。
これは、Symfonyプロジェクトの実行に必要な基本的なNginx設定です。fastcgi_pass
で、PHPコンテナのポート9000を指定しています。ポート9000は、PHP-FPMがリクエストをリッスン(待機)するデフォルトのポートだからです。
次に、docker-compose.ymlにおいて以下のように、PHPコンテナの設定の後にNginxコンテナの設定を追加します。
コンテナをビルドする
次のコマンドでコンテナをビルドします。
コンテナがビルドされると、次のスクリーンショットのようにターミナルに表示されます。
Docker Desktopを開くと、次のスクリーンショットに示すように、新しく作成されたコンテナが表示されます。
Symfonyアプリケーションを作成する
Symfonyアプリケーションを作成するには、PHPコンテナ内でターミナルを起動します。これには2つの方法があります。
- Docker Desktopを使用する。
symfony_docker
アプリケーションを展開すると、このアプリケーションを構成するコンテナを確認できます。以下のスクリーンショットで矢印で示されているボタンをクリックすると、CLIを開始できます。docker exec
コマンドが実行され、操作するためのターミナルが開きます。
- docker execコマンドを直接実行する。これを行うには、次のコマンドを実行します。
選択した方式に関わらず、新しく開いたターミナルで次のコマンドを実行することにより、設定がSymfonyアプリケーションの要件を満たしていることを確認します。
要件を満たしている場合は、ターミナルに次の出力が表示されます。
次に、以下のコマンドを実行して新しいSymfonyプロジェクトを作成します。
成功すると、ターミナルに以下のテキストが表示されます。
アプリケーションが作成されたため、http://localhost:8080/に移動します。次の例のように、デフォルトのSymfonyインデックスページが表示されます。また、appディレクトリを見ると、Symfonyプロジェクトファイルが保持されていることが分かります。
PHPコンテナのCLIに戻り、作成中のアプリケーションの開発依存関係を追加します。次のコマンドを実行します。
データベース内に著名な歴史家による有名な名言を格納し、取得するには、ORM(正確にはDoctrine ORM)が必要になります。また、フロントエンドをレンダリングするにはTwigテンプレートエンジンが必要になります。次のコマンドを実行し、これらの依存関係を追加します。
次に、プロジェクトの作成中にSymfonyが生成した既存の.envファイルから.env.localファイルを作成します。これを行うには、次のコマンドを実行します。
最後に、.env.localのデータベースパラメーターを更新し、アプリケーションがデータベースコンテナに接続できるようにします。ファイルの現在のDATABASE_URL
エントリを以下に置き換えます。
名言エンティティを作成する
次に、MySQLデータベースとの対話を処理するORMエンティティを作成します。これを行うには、Symfony Makerバンドルを使用し、次のコマンドを実行します。
一連の質問に対して次のように答えてください。
Quote.phpという名前のエンティティがsrc/Entityディレクトリに作成されます。src/Entity/Quote.phpを開き、次に示すようにコンストラクタ関数を追加します。
次のコマンドを使用し、データベースを更新するための移行(migration
)を作成します。
次のコマンドを使用し、移行を実行します。
プロンプトが表示されたら「yes」を選択します。「quote」という名前の新しいテーブルでデータベースが更新されます。
作成されたことを確認するには、新しいターミナルウィンドウを開き、symfony_dockerディレクトリ内から次のコマンドを実行します。
ターミナルが開いたら、次のコマンドを使用してデータベースに接続します。
プロンプトが表示されたら、MYSQL_ROOT_PASSWORD
を入力します。接続するデータベースを指定したため、次のコマンドを使用してテーブルに対してクエリを実行できます。
次のような出力が表示されます。
名言フィクスチャを作成する
次に、生成された一連の名言をデータベースに読み込み、アプリの準備ができたとき、名言を取得して表示できるようにします。これを行うには、PHPコンテナで、次のコマンドを実行します。
フィクスチャはsrc/DataFixtures/QuoteFixture.phpにあります。ファイルを開き、以下のように更新します。
データベースにフィクスチャを読み込むには、PHPコンテナで次のコマンドを実行します。
データベースにフィクスチャを読み込むように求められたら、「yes」と応答します。その後、データベースコンテナで次のコマンドを実行し、名言が読み込まれたことを確認します。
テーブルは次のようになっています。
名言コントローラーを作成する
次に、新しいコントローラーを作成します。このコントローラーでは、ORMエンティティを使用してデータベースから名言を取得し、ビューに表示して閲覧できるようにします。これを行うには、PHPコンテナで、次のコマンドを実行します。
コマンドが完了すると、QuoteController.phpという名前の新しいコントローラーがsrc/Controllerディレクトリに作成されます。ファイルを開き、以下のように更新します。
ビューのスタイルを設定する
最後に、ビューの表示を整理し、読みやすくします。これを行うには、Bootstrapを使用してスタイルを設定します。以下のようにapp/templates/base.html.twigを更新します。
次に、app/templates/quote/index.html.twigを開き、以下のように編集します。
{% extends 'base.html.twig' %}
{% block title %}Quotes{% endblock %}
{% block body %}
<style>
.wrapper {
margin: 1em auto;
width: 95%;
}
</style>
<div class="wrapper">
<h1>Great Quotes</h1>
<table class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Quote</th>
<th scope="col">Historian</th>
<th scope="col">Year</th>
</tr>
</thead>
<tbody>
{% for quote in quotes %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ quote.quote }}</td>
<td>{{ quote.historian }}</td>
<td>{{ quote.year }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
アプリケーションをテストする
完成したアプリケーションをテストします。インデックスページをリロードし、データベースに保存されている有名な名言を表示します。
Dockerを使用してSymfonyプロジェクトを設定する方法は以上です
このチュートリアルでは、イメージとDockerfileからコンテナをビルドするだけでなく、相互に通信することもできました。これにより、Symfonyアプリケーションとデータベースを個別のコンテナで実行できました。
同じ仕様でコンテナをビルドすることにより、開発チームは同じコードベースだけでなく、同じ環境で作業できます。
このチュートリアルの全コードベースは、GitHubで入手できます。ぜひご確認ください。コーディングを楽しみましょう!
Oluyemiは、電気通信工学のバックグラウンドを持つテクノロジー愛好家です。ユーザーが直面する日々の問題を解決することに強い関心を持ち、プログラミングの道に進んで以来、Webとモバイルの両方のソフトウェア開発で問題解決能力を磨いてきました。
Oluyemiは、知識の共有に情熱を注ぐフルスタックのソフトウェアエンジニアであり、ブログで多数の技術記事とコンテンツをインターネットに公開しています。テクノロジーにも精通しており、趣味は新しいプログラミング言語とフレームワークを試すことです。
- Twitter: https://twitter.com/yemiwebby
- GitHub: https://github.com/yemiwebby
- Webサイト: https://yemiwebby.com.ng/