はじめに
第1章 Laravelアプリケーションの作成
第2章 Terraformのセットアップ
第3章 ECRの構築とTerraformの基本操作
第4章 GitHub ActionsでイメージをECRにプッシュする
第5章 ネットワーク(VPC)の構築
第6章 ドメインの取得とロードバランサーの構築
第7章 ECS(Fargate)の構築
第8章 GitHub ActionsでFargateにデプロイする
第9章 Laravelとnginxを本番環境向けに修正する
第10章 RDSとプライベートホストゾーンの構築
第11章 ElastiCache(Redis)の構築
付録A 参考文献
おわりに
本書を手に取ってくださり、ありがとうございます。
本書では、nginx + Laravel + MySQL + Redisで構成されるアプリケーションをAWS上に構築する方法を解説します。nginxとLaravelは、AWSのコンテナオーケストレーションサービスであるECS(Fargate)を使用します。また、AWSの各リソースはTerraformで構築し、デプロイはGitHub Actionsでおこないます。
本書では、次のような人を対象としています。
・LaravelをAWS Fargateに自動デプロイする方法を知りたい人
・上記のAWS環境をTerraformで構築する方法を知りたい人
・GitHub Actionsの基本的な使い方を知りたい人
本書を進めるにあたっては、以下が必要です。
・Gitの基本知識(ブランチ作成、コミット、プッシュをおこなえる等)
・GitHubの基本知識(リポジトリ作成、プルリクエスト作成、マージがおこなえる等)
・Docker Desktop for Macをインストール済み
・Homebrewをインストール済み
・AWSアカウントを持っている
本書は、MacOSで動作確認をおこなっています。その他、使用するバージョンは以下の通りです。
・Laravel 8.*
・nginx 1.20
・MySQL 8.0
・Redis 6.*
・Terraform 1.0.0
・TerraformのAWSプロバイダ 3.38.0
・AWS Fargate 1.4.0
本書で作成するコードはGitHubで公開しています。
・https://github.com/shonansurvivors/laravel-fargate-app
・https://github.com/shonansurvivors/laravel-fargate-infra
その他、各章終了時点のコードも用意しているので、参考にしてください。それらへのリンクは、各章の冒頭に記載するようにしています。
本書では、有料のAWSリソースを作成します。できるだけ料金の安い構成にする、有料のリソースをこまめに削除しやすいTerraformのコードにするなど工夫はしていますが、リソースを長期間作りっぱなしにして想定以上の料金を請求されることがないよう注意してください。思わぬ高額請求が不安な方は、以下の記事などを参考に、予想請求額が一定額を超えたら通知メールが飛ぶ設定を入れることをお勧めします。
この章では、ローカル環境でLaravelアプリケーションの作成をおこないます。
本章完了時点のサンプルコードは以下になります。必要に応じて参考にしてください。
・https://github.com/shonansurvivors/laravel-fargate-app/tree/chapter-1
本書では、使いやすいLaravel開発環境として人気が高い、ucan-lab/docker-laravel1をフォークした、筆者のリポジトリをテンプレートとして利用します。
本家のucan-lab/docker-laravelを使っても構わないのですが、日々更新されており、最新版では本書の内容を進められない可能性もあるため、フォークした筆者のリポジトリを使用することをお勧めします。
まず、筆者のGitHubリポジトリにブラウザでアクセスしてください。
・https://github.com/shonansurvivors/docker-laravel
本家のucan-lab/docker-laravelと同様、筆者のGitHubリポジトリもテンプレートリポジトリとなっているため、「Use this template」ボタンが表示されています。この「Use this template」ボタンを使うと、コピー元のコミット履歴は引き継がれずに新規リポジトリが作成されます。
ボタンを押すと、リポジトリ作成画面が表示されます。「Repository name」には、これから作成するリポジトリの名前を入力します。本書ではlaravel-fargate-appとする前提で説明を続けます。入力が終わったら、「Create repository from template」ボタンを押してください。
ボタンを押してリポジトリの作成が終わったら、リポジトリをローカルにクローンします。以下のコマンドを実行してください。
$ git clone https://github.com/{あなたのGitHubアカウント名}/laravel-fargate-app.git
これより先ではローカルのリポジトリに各種変更を加えていきますが、開発ブランチを作成の上、適宜コミットを実施してください。
続いて、リポジトリに用意されたDockerfileからのDockerイメージのビルドと、Laravelのインストールをおこないます。
docker-laravelではmake create-projectとコマンドを打つことで、DockerイメージのビルドやLaravelのインストールに加えて、データベースのマイグレーションなどを一挙に実行してくれます。ただし、インストールされるLaravelは、その時点の最新バージョンとなります。本書ではLaravel8系で動作確認をしているので、8系がインストールされるよう、Makefileのlaravel-installに続く行を以下の通り書き換えてください。
...(省略)...
laravel-install:
docker-compose exec app composer create-project --prefer-dist "laravel/laravel=8.*" .
...(省略)...
Makefileの編集が終わったら、以下コマンドを実行してください。
$ make create-project
処理完了後、ブラウザでlocalhostにアクセスし、以下の画面が表示されれば問題ありません。
今後LaravelをFargateにデプロイした際に、データベースへのアクセスの伴う機能の動作確認をおこなうため、簡単な認証機能を追加します。
Laravelに認証機能を追加するパッケージとしてはLaravel JetstreamやLaravel Breezeがありますが、今回はシンプルなLaravel Breezeを使います。
laravel-fargate-appディレクトリで以下を実行してください。
$ docker-compose exec app composer require laravel/breeze --dev
docker-laravelでは、appコンテナにPHPとComposerがインストールされています。そのため、composerコマンドはappコンテナ上で実行するようにしてください。
Laravel Breezeから各種コントローラーやBlade等を生成します。以下を実行してください。
$ docker-compose exec app php artisan breeze:install
Node.js関連のモジュールをインストールします。以下コマンドを実行してください。
$ docker-compose exec web npm install
docker-laravelでは、webコンテナにNode.jsとnpmがインストールされています。そのため、npmコマンドはwebコンテナ上で実行するようにしてください。
なお、Makefileでは上記コマンドがnpm-installと定義されているので、代わりにmake npm-installと実行しても構いません。
この後、JavaScriptやCSSをトランスパイルしますが、それによって生成されるファイルはGit管理不要です。そのため、.gitignoreを以下の通り編集してください。
/node_modules
/public/css # この行を追加
/public/hot
/public/js # この行を追加
/public/mix-manifest.json # この行を追加
/public/storage
...(省略)...
.gitignoreの編集が終わったらトランスパイルをおこないます。以下コマンドを実行してください。
$ docker-compose exec web npm run dev
Makefileでは上記コマンドがnpm-devと定義されているので、代わりにmake npm-devと実行しても構いません。
ここまでの作業が終わったら、ブラウザでlocalhostにアクセスし、ユーザー登録を実施してみてください。
ユーザー登録後、以下のようにダッシュボード画面に遷移できれば、問題ありません。
最後に本書を進める上では不要な機能を削除します。
docker-laravelでは、GitHub Actions上で定期実行されるテスト処理が定義されています。本書を進める上では不要なので削除してください。
.
└──laravel-fargate-app
└── .github
└── workflows
├── laravel-create-project.yml # 削除
└── laravel-git-clone.yml # 削除
以上で、本章は完了です。
この章では、Terraformを使う準備をします。
本章ではコードの変更はないため、サンプルコードはありません。
Terraformをクライアントにインストールします。今回はHomebrewを使用します。
$ brew install terraform
次に、クライアントで使用するTerraformのバージョンを切り替えることのできる、tfenvをインストールします。
Terraformでインフラを一度新規構築した後、クライアントで使用するTerraformのバージョンを上げると、Terraformの記法や利用できる機能が変わったことを理由として、作成済みのTerraformのコード(tfファイル)を一部書き換える必要が出てくる場合があります。そのため、一度構築したインフラは、いったんは新規構築時に使ったTerraformのバージョンで保守することになります。もし、利用するTerraformのバージョンを上げる際は、移行計画を別途立ててコードの書き換えをおこなうことになるかと思います。
つまり、クライアントでは常時最新バージョンのTerraformを使うのではなく、特定のバージョンに固定して使う必要があります。一方で、複数プロジェクトでTerraformを使用している場合、プロジェクトごとにTerraformのバージョンは異なるでしょうから、クライアントで使用するTerraformは複数のバージョンから切り替えることができないと不便です。そこで、tfenvをインストールします。
tfenvもHomebrewを使ってインストールします。
$ brew install tfenv
もし、以下のようなエラーが出たら、指示に従って、brew unlink terraformを実行した上で、改めてbrew install tfenvを実行してください。
Error: Cannot install tfenv because conflicting formulae are installed.
terraform: because tfenv symlinks terraform binaries
Please `brew unlink terraform` before continuing.
tfenv list-remoteで、tfenvでインストール可能なTerraformバージョンを確認できます。
$ tfenv list-remote
1.0.1
1.0.0
0.15.5
...(省略)...
tfenv installで、指定したバージョンのTerraformをインストールできます。本書では、1.0.0をインストールします。
$ tfenv install 1.0.0
tfenv listで、インストール済みのバージョンと、現在使用中のバージョンが確認できます。「*」が付いているバージョンが現在使用中なのですが、まだ1.0.0に「*」が付いていません。
$ tfenv list
1.0.0
tfenv useで、使用するバージョンを切り替えできます。ここでは、1.0.0を指定してください。
$ tfenv use 1.0.0
Switching default version to v1.0.0
Switching completed
tfenv listを改めて実行すると、使用中のバージョンが1.0.0になったことが確認できます。
$ tfenv list
* 1.0.0 (set by /usr/local/Cellar/tfenv/2.0.0/version)
Terraformを使ってAWSにリソースを作成するには、AWS CLI(Command Line Interface)が必要です。そのため、AWS CLIをインストールします。また、AWS CLIで使用するプロファイルを設定します。
AWS CLIがインストールされているかどうかは、以下のコマンドで確認できます。
$ aws --version
コマンド実行後、以下のようにバージョンが表示されれば、AWS CLIはインストール済みです。
aws-cli/2.1.10 Python/3.9.1 Darwin/19.6.0 source/x86_64 prompt/off
もし、AWS CLIがインストールされていなければ、以下コマンドを実行してください。
$ brew install awscli
インストール完了後、以下のコマンドを実行してください。
$ aws --version
コマンド実行後、以下のようにバージョン表示がされれば問題ありません。
aws-cli/2.1.10 Python/3.9.1 Darwin/19.6.0 source/x86_64 prompt/off
AWS CLIで、あるIAMユーザーの権限で操作するには、そのIAMユーザーのアクセスキーIDとシークレットアクセスキーが必要です。これを発行します。
もし、AWS CLIを普段から使っていて、AdministratorAccess権限を持ったIAMユーザーをプロファイルに設定済みであれば、実施することはありません。「2.5 tfstate管理用のS3バケットの作成」に飛んで、そこから先を読んでください。
AWS CLIを使うのが初めてであったり、プロファイルというものをよく知らないという方は、このまま読み進めてください。
ブラウザからAWSマネジメントコンソールのIAMに移動してください。
左側のメニューから「ユーザー」を選択し、AdministratorAccess権限を持っているIAMユーザーの名前を押してください。
上の画面では、terraformという名前のIAMユーザーを選択していますが、これは筆者のAWSアカウント内だけに存在する、AdministratorAccess権限を持ったIAMユーザーです。実際には、あなたのAWSアカウント内に存在するAdministratorAccess権限を持っているIAMユーザーを選択するようにしてください。
「認証情報」タブを選択すると表示される、「アクセスキーの作成」ボタンを押してください。
以下の画面が表示され、アクセスキーIDとシークレットアクセスキーが確認できるようになります。
この画面は閉じずに、そのままにしておいてください。
アクセスキーIDとシークレットアクセスキーの値は、他人に知られないよう注意してください。たとえば、何かのファイルにメモ代わりに記述して、気づかないうちにうっかりGitHubのパブリックリポジトリにプッシュしてしまった、といったようなことがないようにしてください。もし他人に知られてしまうと、悪用されて高額課金されてしまうというリスクがあります。
先ほどのアクセスキーIDとシークレットアクセスキーを使えるようにAWS CLIに設定すると、AdministratorAccess権限でターミナルからAWSの操作をおこなうことができます。具体的な設定方法としては、環境変数に設定する方法と、プロファイルに設定する方法があります。環境変数に設定する場合は、ターミナルで以下のようにコマンドを実行します。
$ export AWS_ACCESS_KEY_ID=XXX...
$ export AWS_SECRET_ACCESS_KEY=XXX...
$ export AWS_REGION=ap-northeast-1
もうひとつの設定方法であるプロファイルを利用する場合は、上記のような一連の設定に名前を付けて呼び出すことができます。
プロファイルを利用した方が管理しやすいので、本書ではプロファイルの設定方法を説明します。
まず、プロファイルを作成します。ターミナルで以下コマンドを実行してください(実行場所のディレクトリはどこでも構いません)。
terraformの部分は、プロファイルに付ける名前です。terraform以外のお好みの名前でも構いません。
$ aws configure --profile terraform
コマンドを実行すると、最初に以下が表示されます。
AWS Access Key ID [None]:
以下画面のアクセスキーIDの値を貼り付けてください。
入力が終わったら、ターミナルでエンターキーを押してください。
次に以下が表示されます。
AWS Secret Access Key [None]:
以下画面の表示を押すと表示される、シークレットアクセスキーの値を貼り付けてください。
入力が終わったら、ターミナルでエンターキーを押してください。
次に以下が表示されます。
Default region name [None]:
ここでは以下のように、ap-northeast-1(アジアパシフィック東京)と入力してエンターキーを押してください。
Default region name [None]: ap-northeast-1
最後に以下が表示されます。
Default output format [None]:
ここでは以下のように、jsonと入力してエンターを押してください。
Default output format [None]: json
ここで設定したのは、AWS CLIを実行した結果の出力形式です。他にもtextなどが選択1できます。
以上で、一連の設定をひとまとめにしたプロファイルが新規作成されました。この段階ではプロファイルが作成されただけで、まだ使用する状態になっていません。作成したプロファイルを使用するには、環境変数AWS_PROFILEにプロファイル名を設定します。
以下コマンドを実行してください(以下は、プロファイルの名前をterraformで作成した場合の例です)。
$ export AWS_PROFILE=terraform
次に、以下コマンドを実行してください。
$ aws configure list
現在使用中のプロファイルが、表形式で表示されます。
Name Value Type Location
---- ----- ---- --------
profile terraform manual --profile
access_key ****************XXXX shared-credentials-file
secret_key ****************XXXX shared-credentials-file
region ap-northeast-1 config-file ~/.aws/config
profileと書かれた行のValue列の値が、先ほど作成したプロファイルの名前(terraform等)となっていれば問題ありません。
今後、本書でTerraformを使っていく中で、もしも権限不足などでエラーになっていると思われるときは、aws configure listコマンドを使って、正しいプロファイルを使用する設定になっているかどうかを確認するようにしてください。
Terraformでは、インフラの最新の状態をtfstateと呼ばれるファイルで管理します。
このtfstateはデフォルトではローカルに保存されますが、チームでTerraformを扱う場合は、ローカルではなくチーム全員が参照・更新可能な場所に保存する必要があります。
読者の方は1人で本書のチュートリアルを進めていくでしょうから、tfstateをローカルに保存して進めることも可能かと思いますが、チーム開発などにも対応できるよう、tfstateをAWSのストレージサービスであるS3に保存していくようにします。
なお、今回対応は見送りますが、Terraformでは複数人でのtfstateの更新が競合しないよう、DynamoDBを使ってロックをおこなう2こともできます。
S3バケットは先ほど設定が完了したAWS CLIを使って数回のコマンドで作成することもできるのですが、ここではマネジメントコンソールから作成していくことにします。
ブラウザからAWSマネジメントコンソールのS33に移動し、「バケットの作成」を選択してください。
以下の画面が表示されるので、バケット名を入力し、リージョンを選択します。
バケット名は、世界中で他と被らないユニークな名前にする必要があります。画面例では、筆者のSNSなどでのアカウント名を含めるようにして、shonansurvivors-tfstateとしました。読者の方は、何かユニークな名前-tfstateとするようにしてください。
リージョンについては、「アジアパシフィック (東京) ap-northeast-1」を選択してください。
「パブリックアクセスをすべてブロック」はチェックをしたままとします。
「バケットのバージョニング」は「有効にする」を選択してください。
バージョニング4を有効化すると、S3バケット内のオブジェクト(ファイル)を世代管理します。バージョニングを設定しておくことで、tfstateを誤って削除したり更新したりしてしまったときのリカバリが可能となります。
「サーバー側の暗号化」は「有効にする」、「暗号化キータイプ」は「Amazon S3 キー (SSE-S3)」を選択してください。
全ての入力が終わったら、「バケットを作成」を押してください。
以上で本章は完了です。次の章では、Terraformを使って、AWSリソースを作成していきます。