これはパーソルキャリア Advent Calendar 2018の4日目です。
AWS CLIを使ってEC2+nginx+Laravelな環境をCode4兄弟(CodeCommit
, CodeBuild
, CodeDeploy
, CodePipeline
)で継続的デプロイできるようにする手順をまとめてみました。
構築する環境
AWS CLIはMacで実行し必要の都度、EC2にSSHして進めます。
Mac環境は以下です。
EC2環境は以下です。
まずEC2+nginx+Laravelの環境を構築します。そしてCode4兄弟を導入して継続的デプロイできる構成にしていきます。 ここでの継続的デプロイとは、CodeCommit/Laravelプロジェクトのmasterブランチに変更をpushしたら自動でEC2にデプロイされる仕組みのことです。
最終的にCode4兄弟の役割は下記のようにします。
- CodeCommit : LaravelプロジェクトのGitリポジトリを管理する
- CodeBuild :
composer install
を実施してvendorディレクトリ
を生成する - CodeDeploy : EC2インスタンスにLaravelプロジェクト設置しnginxに反映する
- CodePipeline : CodeCommit, CodeBuild, CodeDeployを順に実施する
最終的な構成は下記です。
構築の手順
今回はMac環境に作業ディレクトリを作ってここで作業します。
$ mkdir work $ cd work
最初のEC2+nginx+Laravelな環境を作成する
まずは前提となるVPC環境を作ります。
$ vpc=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16) $ vpc_id=$(echo $vpc | jq -r ".Vpc.VpcId") $ aws ec2 create-tags \ --resources ${vpc_id} \ --tags Key=Name,Value=test-laravel
$ internet_gateway=$(aws ec2 create-internet-gateway) $ internet_gateway_id=$( \ echo $internet_gateway | jq -r ".InternetGateway.InternetGatewayId") $ aws ec2 create-tags \ --resources ${internet_gateway_id} \ --tags Key=Name,Value=test-laravel $ aws ec2 attach-internet-gateway \ --internet-gateway-id ${internet_gateway_id} \ --vpc-id ${vpc_id}
VPCにサブネットを作成します。
$ subnet=$( \ aws ec2 create-subnet \ --vpc-id ${vpc_id} \ --cidr-block 10.0.0.0/24 \ --availability-zone ap-northeast-1a) $ subnet_id=$(echo $subnet | jq -r ".Subnet.SubnetId") $ aws ec2 create-tags \ --resources ${subnet_id} \ --tags Key=Name,Value=test-laravel
ルートテーブルにインターネットゲートウェイのルーティング設定を追加します。
$ route_table_id=$( \ aws ec2 describe-route-tables \ --filters Name=vpc-id,Values=${vpc_id} \ | jq -r ".RouteTables[].RouteTableId") $ aws ec2 create-tags \ --resources ${route_table_id} \ --tags Key=Name,Value=test-laravel $ aws ec2 create-route \ --route-table-id ${route_table_id} \ --destination-cidr-block 0.0.0.0/0 \ --gateway-id ${internet_gateway_id} $ aws ec2 associate-route-table \ --route-table-id ${route_table_id} \ --subnet-id ${subnet_id}
EC2用にSSH(22)とHTTP(80)を許可したセキュリティグループを作成します。
$ security_group=$( \ aws ec2 create-security-group \ --group-name test-laravel \ --vpc-id ${vpc_id} \ --description "test laravel") $ security_group_id=$(echo $security_group | jq -r ".GroupId") $ aws ec2 authorize-security-group-ingress \ --group-id ${security_group_id} \ --protocol tcp \ --port 22 \ --cidr 0.0.0.0/0 $ aws ec2 authorize-security-group-ingress \ --group-id ${security_group_id} \ --protocol tcp \ --port 80 \ --cidr 0.0.0.0/0
EC2インスタンスへのSSHアクセスの為にキーペア/pemを作成します。
$ key_pair=$(aws ec2 create-key-pair --key-name test-laravel) $ echo $key_pair | jq -r ".KeyMaterial" > test-laravel.pem $ chmod 400 test-laravel.pem
EC2インスタンスを作成します。使うAMIはAmazon Linux 2 AMI 2.0.20181114 x86_64 HVM gp2
です。
$ aws ec2 describe-images \ --image-ids ami-0a2de1c3b415889d2 \ --region ap-northeast-1 { "Images": [ { "ImageLocation": "amazon/amzn2-ami-hvm-2.0.20181114-x86_64-gp2", "ImageId": "ami-0a2de1c3b415889d2", "SriovNetSupport": "simple", "ImageType": "machine", "CreationDate": "2018-11-14T09:06:55.000Z", "RootDeviceType": "ebs", "VirtualizationType": "hvm", "Architecture": "x86_64", "ImageOwnerAlias": "amazon", "State": "available", "Hypervisor": "xen", "Description": "Amazon Linux 2 AMI 2.0.20181114 x86_64 HVM gp2", "RootDeviceName": "/dev/xvda", "Name": "amzn2-ami-hvm-2.0.20181114-x86_64-gp2", "OwnerId": "137112412989", "Public": true, "EnaSupport": true, "BlockDeviceMappings": [ { "DeviceName": "/dev/xvda", "Ebs": { "SnapshotId": "snap-0d789818b1297bb21", "Encrypted": false, "VolumeSize": 8, "DeleteOnTermination": true, "VolumeType": "gp2" } } ] } ] } $ ec2=$(aws ec2 run-instances \ --image-id ami-0a2de1c3b415889d2 \ --key-name test-laravel \ --security-group-ids ${security_group_id} \ --subnet-id ${subnet_id} \ --associate-public-ip-address \ --instance-type t2.micro) $ ec2_instance_id=$(echo $ec2 | jq -r ".Instances[].InstanceId") $ aws ec2 create-tags \ --resources ${ec2_instance_id} \ --tags Key=Name,Value=test-laravel
EC2インスタンスにElastic IPを割り当てます。
$ elastic_ip=$(aws ec2 allocate-address) $ ec2_ip=$(echo $elastic_ip | jq -r ".PublicIp") $ elastic_ip_id=$(echo $elastic_ip | jq -r ".AllocationId") $ aws ec2 associate-address \ --allocation-id ${elastic_ip_id} \ --instance ${ec2_instance_id}
$ ssh -i test-laravel.pem ec2-user@${ec2_ip}
続いてEC2インスタンスにnginx+Laravel環境を作ります。
まずは必要なnginxとphp-fpmをインストールします。
$ sudo amazon-linux-extras install nginx1.12 -y $ sudo amazon-linux-extras install php7.2 -y
php-fpmのuserとgroupをnginxに変更します。
$ sudo yum install patch -y $ cat www.conf.patch --- www.conf +++ www.conf @@ -21,9 +21,9 @@ ; Note: The user is mandatory. If the group is not set, the default user's group ; will be used. ; RPM: apache user chosen to provide access to the same directories as httpd -user = apache +user = nginx ; RPM: Keep a group allowed to write in log dir. -group = apache +group = nginx ; The address on which to accept FastCGI requests. ; Valid syntaxes are: $ sudo patch -u /etc/php-fpm.d/www.conf < www.conf.patch
ComposerとLaraveiに必要なPHPパッケージをインストールします。
$ curl -sS https://getcomposer.org/installer | sudo php $ sudo cp composer.phar /usr/local/bin/composer $ sudo ln -s /usr/local/bin/composer /usr/bin/composer $ sudo yum install -y php-mbstring php-xml php-bcmath
Laraveiプロジェクトを作成します。
$ cd /usr/share/nginx/html/ $ sudo composer create-project --prefer-dist "laravel/laravel=5.7.*" test-laravel $ sudo chown -R nginx ./test-laravel* $ cd ~/
nginxのルートディレクトリをLaraveiプロジェクトに変更します。
$ cat nginx.conf.patch --- nginx.conf +++ nginx.conf @@ -39,7 +39,7 @@ listen 80 default_server; listen [::]:80 default_server; server_name _; - root /usr/share/nginx/html; + root /usr/share/nginx/html/test-laravel/public; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; $ sudo patch -u /etc/nginx/nginx.conf < nginx.conf.patch
nginxとphp-fpmを起動するとブラウザ(http://${ec2_ip}
)からアクセスできるようになります🎉
$ sudo systemctl start nginx.service $ sudo systemctl start php-fpm.service
LaravelプロジェクトをCodeCommit管理にする
EC2で作成したLaravelプロジェクトをアーカイブします。
$ cd /usr/share/nginx/html $ sudo tar cvfz test-laravel.tar.gz test-laravel $ cd - $ exit
Laravelプロジェクトのアーカイブを取得・展開してGitリポジトリを作成します。
$ scp -i test-laravel.pem -P 22 ec2-user@${ec2_ip}:/usr/share/nginx/html/test-laravel.tar.gz ./ $ tar xvfz test-laravel.tar.gz $ cd test-laravel $ git init $ git add -A $ git commit -m "Initial commit"
CodeCommitプロジェクトを作成しLaravelプロジェクトをpushします。
$ codecommit=$(aws codecommit create-repository --repository-name test-laravel) $ codecommit_arn=$(echo $codecommit | jq -r ".repositoryMetadata.Arn") $ git remote add origin ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test-laravel $ git push origin master $ cd ..
EC2インスタンスのLaravelプロジェクトのディレクトリ構成を自動デプロイ向けに変更する
下記のようにreleases
へタイムスタンプをディレクトリ名としてLaravelプロジェクトをデプロイします。そしてrelease
のシンボリック先を変更して必要な処理を行います。最後にcurrent
が有効なプロジェクトへのシンボリックリンクになるように切り替えを行う方式にします。
/user/share/nginx/html/test-laravel . ├── .env ├── current -> /user/share/nginx/html/laravel/releases/1533870527 ← ルートディレクトリ ├── release -> /user/share/nginx/html/laravel/releases/1533870527 ← デプロイ作業中のみできる ├── releases │ └── 1533870527 ← タイムスタンプ │ ├── .env -> /user/share/nginx/html/laravel/.env │ ├── strage -> /user/share/nginx/html/laravel/shared/strage │ └── その他のtest-laravelコード └── shared └──strage
まず、nginxとphp-fpmを停止します。
$ ssh -i test-laravel.pem ec2-user@${ec2_ip} $ sudo systemctl stop nginx.service $ sudo systemctl stop php-fpm.service
ディレクトリ構成を変更します。
$ cd /usr/share/nginx/html/ $ timestamp=$(date +%s) $ sudo mv test-laravel ${timestamp} $ sudo mkdir -p test-laravel $ cd test-laravel $ sudo mkdir -p ./shared $ sudo mkdir -p ./releases $ sudo mv ../${timestamp} ./releases/ $ deploy_path="/usr/share/nginx/html/test-laravel" $ sudo ln -nfs "${deploy_path}/releases/${timestamp}" ./release $ sudo mv ./release/storage ./shared/ $ sudo mv ./release/.env ./ $ cd ./release $ sudo ln -nfs ${deploy_path}/.env ./.env $ sudo ln -nfs ${deploy_path}/shared/storage ./storage $ cd ../ $ sudo ln -nfs "${deploy_path}/releases/${timestamp}" ./current $ sudo unlink ./release $ cd ../ $ sudo chown -R nginx ./test-laravel* $ cd ~/
nginxのルートディレクトリを新しいディレクトリ構成に変更します。
$ cat nginx.conf.2.patch --- nginx.conf +++ nginx.conf @@ -39,7 +39,7 @@ listen 80 default_server; listen [::]:80 default_server; server_name _; - root /usr/share/nginx/html/test-laravel/public; + root /usr/share/nginx/html/test-laravel/current/public; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; $ sudo patch -u /etc/nginx/nginx.conf < nginx.conf.2.patch
nginxとphp-fpmを起動すると新しいディレクトリ構成でブラウザ(http://${ec2_ip}
)からアクセスできるようになります🎉
$ sudo systemctl start nginx.service $ sudo systemctl start php-fpm.service $ exit
CodeDeploy環境を整える
CodeDeployエージェントのためのIAMロールを作成してEC2インスタンスに割り当てます。
$ cat codedeploy-ec2-trust.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } $ aws iam create-role \ --role-name test-laravel-ec2 \ --assume-role-policy-document file://codedeploy-ec2-trust.json $ cat codedeploy-ec2-permissions.json { "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:Get*", "s3:List*" ], "Effect": "Allow", "Resource": "*" } ] } $ policy_ec2=$( \ aws iam create-policy \ --policy-name test-laravel-ec2 \ --policy-document file://codedeploy-ec2-permissions.json) $ policy_ec2_arn=$(echo $policy_ec2 | jq -r ".Policy.Arn") $ aws iam attach-role-policy \ --policy-arn ${policy_ec2_arn} \ --role-name test-laravel-ec2 $ aws iam create-instance-profile \ --instance-profile-name test-laravel $ aws iam add-role-to-instance-profile \ --role-name test-laravel-ec2 \ --instance-profile-name test-laravel $ aws ec2 associate-iam-instance-profile \ --instance-id ${ec2_instance_id} \ --iam-instance-profile Name=test-laravel
EC2インスタンスにCodeDeployエージェントをインストールします。
$ ssh -i test-laravel.pem ec2-user@${ec2_ip} $ sudo yum update $ sudo yum install ruby -y $ sudo yum install wget -y $ wget https://aws-codedeploy-ap-northeast-1.s3.amazonaws.com/latest/install $ chmod +x ./install $ sudo ./install auto $ exit
CodeDeployのアプリケーションとデプロイグループを作成します。
$ cat deploy_trust_policy.json { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "codedeploy.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } $ role_deploy=$(aws iam create-role --role-name test-laravel-deploy \ --assume-role-policy-document file://deploy_trust_policy.json) $ role_deploy_arn=$(echo $role_deploy | jq -r ".Role.Arn") $ aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole \ --role-name test-laravel-deploy $ aws deploy create-application --application-name test-laravel $ aws deploy create-deployment-group \ --application-name test-laravel \ --deployment-group-name test-laravel \ --deployment-config-name CodeDeployDefault.AllAtOnce \ --ec2-tag-filters Key=Name,Value=test-laravel,Type=KEY_AND_VALUE \ --service-role-arn ${role_deploy_arn}
デプロイスクリプトaws_deploy.sh
とCodeDeploy向けの構築定義ファイルappspec.yml
をLaravelプロジェクトに追加します。
$ cd test-laravel $ mkdir bin $ cat bin/aws_deploy.sh
aws_deploy.sh
の内容は下記です。
#!/bin/bash deploy_path="/usr/share/nginx/html/test-laravel" # デプロイ先 cd ${deploy_path} || exit 99 timestamp=$(date +%s) # 必要なディレクトリを作成 mkdir -p ./shared mkdir -p "./releases/${timestamp}" # 作業ディレクトリにデプロイ ln -nfs "${deploy_path}/releases/${timestamp}" ./release cp -arf /tmp/test_laravel/* ./release/ # デプロイ対象外ファイルを用意 if [ ! -d ./shared/storage ]; then cp -arf ./release/storage ./shared/ chmod 777 -R ./shared/storage fi chown -R nginx ./* cd ./release || exit 99 # デプロイ対象外ファイルをシンボリックリンク化 rm -f .env ln -nfs ${deploy_path}/.env ./.env chown -h nginx ./.env rm -rf ./storage ln -nfs ${deploy_path}/shared/storage ./storage chown -h nginx ./storage # 各種コマンド実施 php artisan storage:link php artisan view:clear php artisan cache:clear composer dump-autoload --optimize cd ../ || exit 99 # デプロイ実施 ln -nfs "${deploy_path}/releases/${timestamp}" ./current unlink ./release # php-fpm/nginx再起動して適用 systemctl restart php-fpm.service systemctl restart nginx.service
続きます。
$ chmod 755 bin/aws_deploy.sh $ cat appspec.yml
appspec.yml
の内容は下記です。
version: 0.0 os: linux files: - source: ./ destination: /tmp/test_laravel permissions: - object: /tmp/test_laravel pattern: "**" owner: nginx hooks: AfterInstall: - location: bin/aws_deploy.sh timeout: 300
続きます。
$ git add -A $ git commit -m "Add support for CodeDeploy" $ git push origin master $ cd ..
CodeBuild環境を整える
まずCodeBuildプロジェクトをEC2インスタンスと同じ環境にするためECRにAmazon Linux 2 AMI 2.0.20181114 x86_64 HVM gp2
のdockerイメージを登録して使えるようにします。
$ ecr_login=$(aws ecr get-login --no-include-email) $ echo $ecr_login > ecr_login.sh $ chmod 755 ecr_login.sh $ bash ./ecr_login.sh $ ecr_repo=$(aws ecr create-repository --repository-name test-laravel) $ ecr_repo_url=$(echo $ecr_repo | jq -r ".repository.repositoryUri") $ docker pull amazonlinux:2.0.20181114 $ docker tag amazonlinux:2.0.20181114 ${ecr_repo_url}/test-laravel:latest $ docker push ${ecr_repo_url}:latest
CodeBuildからアクセスできるようにECRを設定します。
$ cat ecr_policy.json { "Version": "2008-10-17", "Statement": [ { "Sid": "CodeBuildAccess", "Effect": "Allow", "Principal": { "Service": "codebuild.amazonaws.com" }, "Action": [ "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "ecr:BatchCheckLayerAvailability" ] } ] } $ aws ecr set-repository-policy --repository-name test-laravel --policy-text file://ecr_policy.json
CodeBuildのIAMロールを作成します。
$ cat codebuild-trust-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "codebuild.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } $ role_build=$(aws iam create-role --role-name test-larabel-build \ --assume-role-policy-document file://codebuild-trust-policy.json) $ role_build_arn=$(echo $role_build | jq -r ".Role.Arn") $ aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess \ --role-name test-larabel-build
CodeBuildを作成します。
$ cat Source.json { "type": "CODECOMMIT", "location": "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test-laravel" } $ cat Artifacts.json { "type": "NO_ARTIFACTS" } $ cat Environment_Template.json { "type": "LINUX_CONTAINER", "image": ":ecr_repo_url::latest", "computeType": "BUILD_GENERAL1_SMALL" } $ cat Environment_Template.json | sed s/:ecr_repo_url:/$(echo ${ecr_repo_url} | sed "s/\//\\\\\//g")/ > Environment.json $ aws codebuild create-project --name test-laravel \ --source file://Source.json \ --artifacts file://Artifacts.json \ --environment file://Environment.json \ --service-role ${role_build_arn}
CodeBuild向けの構築定義ファイルbuildspec.yml
をLaravelプロジェクトに追加します。
$ cd test-laravel $ cat buildspec.yml
buildspec.yml
の内容は下記です。
version: 0.2 phases: install: commands: - | amazon-linux-extras install php7.2 -y yum install -y php-mbstring php-xml php-bcmath curl -sS https://getcomposer.org/installer | php cp composer.phar /usr/local/bin/composer ln -s /usr/local/bin/composer /usr/bin/composer yum install -y git yum install -y zip unzip build: commands: - rm -rf .git .gitignore README.md - composer install --verbose --prefer-dist --no-progress --no-interaction --no-dev --optimize-autoloader artifacts: files: - '**/*'
続きます。
$ git add -A $ git commit -m "Add support for CodeBuild" $ git push origin master $ cd ..
CodePipeline環境を整える
CodePipeline向けのIAMロールを作成します。
$ cat codepipeline-trust-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "codepipeline.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } $ role_pipeline=$(aws iam create-role --role-name test-larabel-pipeline \ --assume-role-policy-document file://codepipeline-trust-policy.json) $ role_pipeline_arn=$(echo $role_pipeline | jq -r ".Role.Arn") $ aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess \ --role-name test-larabel-pipeline
$ aws s3 mb s3://test-laravel-pipeline --region ap-northeast-1
CodePipelineを作成します。
$ cat pipeline_template.json { "version": 1, "name": "test-laravel", "roleArn": ":role_pipeline_arn:", "artifactStore": { "type": "S3", "location": "test-laravel-pipeline" }, "stages": [ { "name": "Source", "actions": [ { "inputArtifacts": [], "configuration": { "PollForSourceChanges": "true", "BranchName": "master", "RepositoryName": "test-laravel" }, "name": "Source", "outputArtifacts": [ { "name": "SourceArtifact" } ], "actionTypeId": { "version": "1", "category": "Source", "owner": "AWS", "provider": "CodeCommit" }, "runOrder": 1 } ] }, { "name": "Build", "actions": [ { "inputArtifacts": [ { "name": "SourceArtifact" } ], "configuration": { "ProjectName": "test-laravel" }, "name": "Build", "outputArtifacts": [ { "name": "BuildArtifact" } ], "actionTypeId": { "version": "1", "category": "Build", "owner": "AWS", "provider": "CodeBuild" }, "runOrder": 1 } ] }, { "name": "Deploy", "actions": [ { "inputArtifacts": [ { "name": "BuildArtifact" } ], "configuration": { "DeploymentGroupName": "test-laravel", "ApplicationName": "test-laravel" }, "name": "Deploy", "outputArtifacts": [], "actionTypeId": { "version": "1", "category": "Deploy", "owner": "AWS", "provider": "CodeDeploy" }, "runOrder": 1 } ] } ] } $ cat pipeline_template.json | sed s/:role_pipeline_arn:/$(echo ${role_pipeline_arn} | sed "s/\//\\\\\//g")/ > pipeline.json $ aws codepipeline create-pipeline --pipeline file://pipeline.json $ pipeline=$(aws codepipeline get-pipeline --name test-laravel) $ pipeline_arn=$(echo $pipeline | jq -r ".metadata.pipelineArn")
作成すると自動で実行が開始してmasterブランチがデプロイされます🎉 結果はコンソールで確認できます。
CodeBuildをキャッシュ対応する
このままでも動くのですが毎回composer installを実行するのは無駄です。composer.lockに変化がない場合は前回キャッシュしたvendorを使うようにします。
$ aws s3 mb s3://test-laravel-codebuild-cache --region ap-northeast-1
CodeBuildにキャッシュ設定を行います。
$ cat codebuild_cache.json { "type": "S3", "location": "test-laravel-codebuild-cache" } $ aws codebuild update-project --name test-laravel --cache file://codebuild_cache.json
Laravelプロジェクトのbuildspec.yml
を更新します。
$ cat buildspec.yml.patch
buildspec.yml.patch
の内容は下記です。
--- buildspec.yml +++ buildspec.yml @@ -4,20 +4,36 @@ install: commands: - | - amazon-linux-extras install php7.2 -y - yum install -y php-mbstring php-xml php-bcmath + yum install -y tar + if [ -e /tmp/composer.lock ] && [ -e /tmp/vendor.tar ]; then + diff /tmp/composer.lock ./composer.lock + if [ $? -eq 0 ]; then + tar xf /tmp/vendor.tar + fi + fi + if [ ! -e ./vendor ]; then + amazon-linux-extras install php7.2 -y + yum install -y php-mbstring php-xml php-bcmath - curl -sS https://getcomposer.org/installer | php - cp composer.phar /usr/local/bin/composer - ln -s /usr/local/bin/composer /usr/bin/composer + curl -sS https://getcomposer.org/installer | php + cp composer.phar /usr/local/bin/composer + ln -s /usr/local/bin/composer /usr/bin/composer - yum install -y git - yum install -y zip unzip + yum install -y git + yum install -y zip unzip + fi build: commands: - rm -rf .git .gitignore README.md - - composer install --verbose --prefer-dist --no-progress --no-interaction --no-dev --optimize-autoloader - + - if [ ! -e ./vendor ]; then composer install --verbose --prefer-dist --no-progress --no-interaction --no-dev --optimize-autoloader; fi + post_build: + commands: + - cp composer.lock /tmp + - tar cf /tmp/vendor.tar vendor artifacts: files: - '**/*' +cache: + paths: + - /tmp/composer.lock + - /tmp/vendor.tar
続きます。
$ patch -u ./test-laravel/buildspec.yml < buildspec.yml.patch $ cd test-laravel $ git add -A $ git commit -m "Use CodeBuild cache" $ git push origin master $ cd ..
CodeBuildを実行するとS3バケットにvendorのキャッシュが作成されます。 結果はコンソールから確認できます。
$ aws codepipeline start-pipeline-execution --name test-laravel
再度CodeBuildを実行するとvendorのキャッシュが使われるので短い時間で完了します🎉 結果はコンソールから確認できます。
$ aws codepipeline start-pipeline-execution --name test-laravel
CloudWatch EventsでCodePipelineが自動実行されるよう設定する
CodeCommitを監視するCloudWatch Events向けのIAMロールを作成します。
$ cat cwe-trust-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } $ role_cwe=$(aws iam create-role --role-name test-laravel-cwe \ --assume-role-policy-document file://cwe-trust-policy.json) $ role_cwe_arn=$(echo $role_cwe | jq -r ".Role.Arn") $ aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess \ --role-name test-laravel-cwe
CloudWatch Eventsを作成します。
$ cat event_pattern_template.json { "source": [ "aws.codecommit" ], "detail-type": [ "CodeCommit Repository State Change" ], "resources": [ ":codecommit_arn:" ], "detail": { "event": [ "referenceCreated", "referenceUpdated" ], "referenceType": [ "branch" ], "referenceName": [ "master" ] } } $ cat event_pattern_template.json | sed s/:codecommit_arn:/$(echo ${codecommit_arn} | sed "s/\//\\\\\//g")/ > event_pattern.json $ aws events put-rule \ --name "TestLaravel" \ --event-pattern file://event_pattern.json \ --role-arn ${role_cwe_arn} $ aws events put-targets \ --rule TestLaravel \ --targets "Id"="1","Arn"="${pipeline_arn}","RoleArn"="${role_cwe_arn}"
これでmasterへのpushでCodePipelineが自動実行されるようになりました🎉🎉🎉 結果はコンソールから確認できます。
$ cat welcome.blade.php.patch --- welcome.blade.php +++ welcome.blade.php @@ -81,7 +81,7 @@ <div class="content"> <div class="title m-b-md"> - Laravel + Hello World! </div> <div class="links"> $ patch -u ./test-laravel/resources/views/welcome.blade.php < welcome.blade.php.patch $ cd test-laravel $ git add -A $ git commit -m "Test master push" $ git push origin master $ cd ..
しばらくしてブラウザ(http://${ec2_ip}
)からアクセスするとトップページの文字列がLaravel
からHello World!
に変わります。
まとめ
今回はプライベートな時間を利用してLaravelプロジェクトをCodeCommitのmasterブランチにpushしたらEC2に自動デプロイされる環境を構築する手順をまとめました。Code4兄弟でのデプロイ環境構築の経験はコンソールで少しありましたがCLIはほぼ無かったので勉強になりました。
構築した環境には改善した方が良い点もたくさんありますので今回の手順を土台にして色々と挑戦してみるのも良いかもしれません。