LaravelをDockerで動かしてみた on AWS EC2 with CloudFormation
超初学者がPHPフレームワークLaravelをAWS上で動かしてみました。備忘録です。
この記事のきっかけ
- 実務でPHP(Laravel)を使う+新しい言語を学ぶ時はDockerで動かすように意識しているため、とりあえずDockerでLaravelを動かしたい
- AWS認定試験を受けてはいるものの資格一辺倒で名ばかりになりがちを脱するため、AWS上で動かしたい
(所有:SAA / 受験予定:SOA) - やったことを記事にすると、作業中にとっ散らかった脳内を整理できる
この記事で話すこと
- 簡単な手順(備忘録)
- 必要だったこと、学んだことなどの所感
やったこと
下準備(Laravel on Docker編)
Dockerの基礎を学んだ
今までなんとなーく使っていたDockerについてなんとなーくだと通用しなくなってきたので、こちらで基礎を学びました。この知識が最低限だと今では感じていますが、最低限の分量が濃い。
Dockerで何かしらの環境構築を行う際にDockerfileやdocker-compose.ymlの書き方を調べて先人の知恵を借りて(あるいはChatGPT頼み)なんとか構築しますが、なぜその書き方なのかだったり書いてあること1行1行の意味だったりを理解できるようになりました。理解できるおかげで自分の欲しい環境を(簡単であれば)自力で構築することもできそうです。うれしい。DockerでLEMP環境(Laravel+nginx+MySQL)構築
Docker内にLaravel(APP)+WEBサーバー+DBサーバーが欲しかったのでこちらを参考にしました。今回使用しているDockerfile、docker-compose.ymlはほぼこの記事通りです。
上記zenn本を一通り読んだおかげでさくさく進む。下準備(AWS編)
せっかくなのでCloudFormationで構築してみた
SOA受験予定なのでCloudFormationを使ってみました。
サーバーレス構成しか触ったことがなくて基本的な構成の構築経験ほぼゼロなのにコンソールをすっ飛ばしていきなりコードで書くのは無茶だったかな…?!と途中で心が折れそうになりましたがコードで書くからこそ浅い理解では通用しなくて勉強になりました。
参考:
ついでにせっかくなのでAMIはAmazonLinux2023を使用。
さらにせっかくなのでSessionManagerでEC2に接続してみた
触ったことないものを触ってみよう精神です。
参考:
今回はパブリックサブネット上なのでVPCエンドポイントは不要。
SessionManagerでEC2に接続するためのIAMロールの割り当ては必須。
実際に動かした構成
パブリックサブネット上にEC2を立ててIGW経由でアクセスする超簡略構成です。(VPCエンドポイントを使ってSessionManagerでプライベートサブネット上のEC2に接続してみるため、EC2 on プライベートサブネット + NATゲートウェイ on パブリックサブネットとかも試しはしました)
Parametersを使わずハードコードしているのは目を瞑って…🥲
AWSTemplateFormatVersion: "2010-09-09"
Description: "PHP on EC2"
Resources:
# VPC
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: "Name"
Value: "PHP-test-VPC"
# サブネット
MyPublicSubnet:
Type: "AWS::EC2::Subnet"
Properties:
CidrBlock: 10.0.192.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: "Name"
Value: "PHP-test-PublicSubnet"
VpcId: !Ref MyVPC
# IGW設定
MyInternetGateway:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: "Name"
Value: "PHP-test-IGW"
AttachIGW:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
VpcId: !Ref MyVPC
InternetGatewayId: !Ref MyInternetGateway
# ネットワーク設定/Public
MyPublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyVPC
Tags:
- Key: "Name"
Value: "PHP-test-PublicRouteTable"
MyPublicRoute:
Type: AWS::EC2::Route
DependsOn: MyInternetGateway
Properties:
RouteTableId: !Ref MyPublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref MyInternetGateway
PublicSubnetRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref MyPublicSubnet
RouteTableId: !Ref MyPublicRouteTable
# EC2定義
MyEC2forPHP:
Type: "AWS::EC2::Instance"
Properties:
ImageId: "ami-08a706ba5ea257141"
InstanceType: "t2.micro"
SubnetId: !Ref MyPublicSubnet
KeyName: "XXX"
Tags:
- Key: "Name"
Value: "PHP-test-EC2"
SecurityGroupIds:
- !Ref EC2SecurityGroup
IamInstanceProfile: !Ref EC2InstanceProfile
EC2SecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "PHP-test-EC2-SecurityGroup"
VpcId: !Ref MyVPC
Tags:
- Key: "Name"
Value: "PHP-test-SecurityGroup"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: "22"
ToPort: "22"
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: "8081"
ToPort: "8081"
CidrIp: 0.0.0.0/0
EC2InstanceProfile:
Type: "AWS::IAM::InstanceProfile"
Properties:
Path: /
Roles:
- Ref: EC2IAMRole
InstanceProfileName: !Sub PHP-test-EC2InstanceProfile
# IAM定義
EC2IAMRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: !Sub php-test-env-SSM-role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
記事を参考にする際はあらゆる条件・環境をその記事に合わせることがセオリーなのは承知の上でいろいろはみ出してみたら当たり前にいろいろ噛み合わず、ハマる。
基本的なネットワーク設定など文言上は理解していてもいざ構築すると抜け落ちていたり(プライベートサブネット上ではインターネットからのDLができないからNATゲートウェイを使うとか、そういうレベルで)実際に手を動かすことで改めて勉強になりました。
EC2上にDockerとgitをインストール
セッションマネージャーでEC2に接続後、GitHub上のLaravelプロジェクトをEC2にgit clone
してDockerで起動したいのでDocker Engine+Docker Composeとgitをインストールします。
Docker EngineとDocker Composeをインストール
参考:
まずはDocker Engineをインストール。$ sudo dnf install -y docker #Docker Engineをインストール
$ sudo systemctl enable --now docker #システム起動時のDocker自動起動を有効化+起動
$ systemctl status docker #Dockerサービスの状態を確認
できました。
ec2-userでroot権限なしでdockerコマンドを操作できるように。
$ sudo usermod -aG docker ec2-user #Docker Engineインストール時に作成されたdockerグループにec2-userを追加
$ sudo su ec2-user #ec2-userに切り替え
$ docker -v #dockerコマンドが使えることを確認
続いてDocker Composeをインストール。
上記記事を参考にしつつ、Docker公式も確認して最新バージョンをインストール。
$ DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker}
$ sudo mkdir -p $DOCKER_CONFIG/cli-plugins
$ sudo curl -SL https://github.com/docker/compose/releases/download/v2.20.3/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose #ここはDocker公式ドキュメント記載の最新バージョンに置き換える⚠️
$ sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose #docker-composeの実行権限を適用
gitをインストール
$ sudo dnf install -y git
git configでgitの設定+SSHキーの作成でgitのセットアップは完了。
Laravelプロジェクトをインストール+Dockerで動かす on EC2
ec2-userでログインしてLaravelプロジェクトをgit clone
+ docker compose up
で起動。
下準備(Laravel on Docker編)で作成したものをそのままEC2上で動かす感じです。だんだん見えてきてうれしい。
$ git clone git@github.com:XXXXX/XXXXXX.git #git clone
$ cd XXXXX #プロジェクトのルートディレクトリに移動
$ docker compose up
今回はパブリックサブネット上のEC2で簡単に動かしているので、http://{パブリック IPv4 アドレス}:8081
にアクセスして確認!
ハマりポイント
- Laravel関連エラー
composer create-project
でプロジェクト作成すると.gitignore記載のgit管理されないディレクトリとファイルがいくつかあるのでEC2上にgit clone
した時にセットする必要がある、など。初歩的ですが実際に動かしてみると初めての時は見落としがち。 - EC2無料枠t2.microでCPU使用率が100%近くに
dockerコンテナ内で(Laravel関連エラー対処のため)compose update
しようとすると何もできなくなったのでコンソールのモニタリングを確認したところCPU使用量が一気に増してクレジットも使い切っていました。
コンテナ内ではなくEC2上にphpとcomposerをインストールして操作したら大丈夫でした。
まとめ
Laravel on DockerをAWSで動かすベストプラクティスではないだろうということは百も承知で(何よりネットワーク設定がガバガバ)、学習のためにいろいろ触ってみました。
やったこと(まとめ)
- DockerでLEMP環境構築
- CloudFormationでEC2立ち上げ+SessionManager使用
- EC2にLaravelデプロイ+Docker起動
所感
- Docker学び直してよかった
もうDocker怖くない(多分) - 座学で知っていても実際に触ると何も分からない
CloudFormationのテンプレートを書いていて、何も分かってないなあと痛感しました。とはいえ初学者こそインフラをコードで書いてみると得られるものが大きいとも感じました。またやりたい、やる。 - 認定試験の勉強で知っていること、実際に手を動かして分かることで学びの相乗効果
試験勉強で知ったことを構築中に見ると「あ、あれ!」となるし、逆に手を動かして知っていることを試験問題で見た時も「あ、あれ!」となります。このバランスがかなり楽しい。
今は新しい言語やフレームワークを学ぶ時は文法や書き方だけではなく動作の仕組みやインフラ面を理解したいと考えています。まず動く、その上でコードをいじる方が効率がいいと感じているからです。何かあった時に動かない理由を下からつぶしていく、みたいな。
今回はLaravelの挙動についてはあまり触れていませんが、まず「動かす」ことができたので次はLaravelそのものの学習を進めていこうと思います。
Docker学び直し+AWS上で動かしてみるということをやってみていろいろと解像度が上がりました。この一連の流れで同時に学べることが多くあったのもよかったです。
本当はもっとこうすべき、とかこうした方がいい、とかこういうこともあるよーみたいなことがあれば教えてもらえるとうれしいです。
Discussion