100分で本番デプロイ!Laravelで作るWebアプリケーション作成の作業手順書全公開
事前チェック
- Docker入ってますか!? ->
docker -v - Git入ってますか? ->
git -v - Githubのアカウント持ってますか? -> ログインしておきましょう
- AWSのアカウントを用意してきましたか? -> ログインしておきましょう
Githubにソースコードをpushできないパターンがありました。事前に秘密鍵を登録して、ローカルマシンからGithubにソースコードをpushできるようにしておきましょう。
注:本ワークショップで作成するテキストファイルのインデントはすべてスペースです。タブではありません。
手順1 プロジェクトディレクトリの作成とソースコードのpush
1-1 プロジェクトディレクトリの作成
mkdir piseka
以下、pisekaディレクトリ内で作業
1-2 README.md 作成
# piseka
100分以内に価値を届けるプロジェクト
1-3 初期コミット
git init
main ブランチであることを確認しておく
git branch --show-current
main じゃない場合は git branch -m main で main ブランチへ切り替え
そしてコミット
git add README.md
git commit -m 'initial'
1-4 Github Repository作成
Githubへ

リポジトリー名は任意ですが絶対に Private リポジトリーを作ってください

CI/CD設定では認証情報などを取り扱います。オペレーションミスでGithubで公開してしまうなどの事故も発生しうるので、最悪失敗しても大丈夫なように、privateリポジトリで作業しましょう。
1-5 Git Push
git remote の URLをコピー

git remote add origin git@github.com:xxxxx/piseka.git
git push origin main
手順1のチェックポイント
GithubにREADME.mdがpushされた状態です。

手順2 最小のPHPアプリケーション作成
2-1 アプリケーション作成
src ディレクトリを作成して、 index.php を新規作成。
.
├── README.md
└── src
└── index.php
index.php の中身
<?php
echo 'Hello Piseka!';
Dockerfile, compose.yml を追加
.
├── Dockerfile
├── README.md
├── compose.yml
└── src
└── index.php
Dockerfile
FROM php:8.4-apache-bullseye
COPY src /var/www/html
compose.yml
services:
web:
build: .
ports:
- "80:80"
volumes:
- ./src:/var/www/html
2-2 動作確認
docker compose up
ブラウザで確認

2-3 commit & push
git add .
git commit -m 'First App'
git push origin main
手順2のチェックポイント
最小のアプリケーションがpushされた状態

手順3 AWSの準備
AWSログイン後の一番最初の確認として、AWSのリージョン設定が東京であることを確認しましょう。

以下の手順内でリージョンを東京 ap-northeast-1 に固定しているので、この確認はとても大切です。
3-1 コンテナレジストリの作成
AWSの上部検索窓に Elastic Container Registry と入力。Elastic Container Registry が絞り込まれるのでクリック。

作成、またはリポジトリの作成をクリック
リポジトリ名は piseka-repo にします。ここは合わせてください

リポジトリが作成されたら、リポジトリを選択状態にします

その状態で、右上のアクション -> 概要をクリック

ARNが表示されるので、控えておきます

3-2 IAMポリシーの作成
ポリシーはAWSサービスのアクセス制御を定義するものです。Github Actionsにビルドやらデプロイやらをやってもらうのですが、すべての権限を与えるのは危ないので、限られた権限に絞り込むために作ります。
AWSの上部検索窓に IAM と入力するとサービスが表示されます。IAMをクリック。

左側メニューでポリシーをクリック

ポリシーの一覧画面が表示されたら、右上の「ポリシーの作成」をクリック
次にポリシーエディタの JSON をクリック

下記のJSONの中段、Resourceの項目に先ほど控えておいた ECR の ARN を入力します
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ecr:GetAuthorizationToken",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ecr:InitiateLayerUpload",
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage",
"ecr:PutImage",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload"
],
"Resource": "<<<ここにコピーしたARNをいれる>>>"
},
{
"Effect": "Allow",
"Action": [
"ecs:UpdateService",
"ecs:DescribeServices",
"ecs:DescribeTaskDefinition",
"ecs:RegisterTaskDefinition"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*"
}
]
}
次へを入力すると、ポリシー名を入力する画面になります。あとで見たときに判別しやすいポリシー名をつけましょう。名前は任意で大丈夫です。 ポリシーの作成をクリックすると、ポリシーが出来上がります。

3-3 IAMユーザーの作成
このユーザーがGithub Action内で、Dockerコンテナのビルド、コンテナレジストリへのPushを行います。とても大切なユーザーです。
左側のメニューからユーザーをクリック

右上にある ユーザーの作成 をクリック
ユーザー名を入力。任意の名前でOKですが piseka-deploy piseka-github-action など、ユーザー名から役割が類推しやすいようにつけましょう。

次は、ユーザーに権限を設定します。先程のポリシーを直接アタッチします。

次へを押して、確認画面を経て、「ユーザーの作成」です。成功すると、ユーザー一覧画面に遷移します。

3-4 認証情報の取得
先程のユーザー一覧にて、作成したユーザー名のリンクをクリックします。
次に「セキュリティ認証情報」タブをクリック(危ない情報が沢山ある画面です)

アクセスキーを作成をクリック

CLIにチェックを入れて、一番下のチェックボックスにチェックを入れて次へ
※現在は、よりセキュアなアクセス方法が推奨ですが、アクセスキーがもっとも直感的な方法なので今回はあえて選択しています。

次へ、「アクセスキーを作成」をクリック。
※アクセスキー、シークレットアクセスキーが表示されます。
要注意です、シークレットアクセスキーは、作成後のこの画面以外では取得できません。
3-5 Github Secrets にアクセスキー、シークレットアクセスキーを設定する
Githubのpisekaリポジトリにもどって、 Settings をクリック

左メニュー。Secrets and variables -> Actions をクリック

Repository Secrets を作成。ここ重要です。Secretsです。Variables ではありません。

AWS_ACCESS_KEY_ID という名前でアクセスキーを設定
AWS_SECRET_ACCESS_KEY という名前でシークレットアクセスキーを設定

手順3のチェックポイント
こんな感じで、アクセスキー、シークレットアクセスキーが設定されればOK

ここが前半の山です。OIDCを使うのが近年の流行りのようですが、100分だときついので今回は古き良き方法を使います。
手順4 Github Actions
.github/workflows/deploy.yml を作成します
.
├── Dockerfile
├── README.md
├── compose.yml
├── .github/
│ └── workflows
│ └── deploy.yml
└── src
└── index.php
deploy.yml の中身
name: deploy piseka
on:
push:
branches:
- main
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: latest
run: |
docker build -t $ECR_REGISTRY/${{ secrets.ECR_REPOSITORY }}:$IMAGE_TAG -f Dockerfile .
docker push $ECR_REGISTRY/${{ secrets.ECR_REPOSITORY }}:$IMAGE_TAG
echo "::set-output name=image::$ECR_REGISTRY/${{ secrets.ECR_REPOSITORY }}:$IMAGE_TAG"
コミットまでしておく。まだpushしません。
git add .
git commit -m 'github actions'
4-2 足りない Secret を追加する
ECR_REPOSITORY というキー名でECRのリポジトリー名を入力する。
自分でつけたリポジトリの名前を設定しましょう。先程同様に Repository Secrets に登録します。
※Secretsじゃなくても良さそうな情報ですが、手順の簡便化のためにすべてSecretsにしてます

4-3 Github に Push して Actions にコンテナのビルド&PUSHを行わせる
git push origin main
Githubのリポジトリページで Actions をクリックして表示

緑になったらOK

手順4のチェックポイント
ECRにコンテナがpushされていること

これでCIの雛形ができました。あとはCD(デプロイ)です。
自動でコンテナレジストリが更新されるとむねあつですね!
手順5 ECSを使ってアプリケーションを本番公開する
5-1 本番環境 ECSクラスター作成

左メニューから「クラスター」を選択、右上にある「クラスターの作成」クリック

クラスター名を入力、AWS Fargateを選択して作成

クラスター作成は、タイミングによっては500エラーで失敗します。そのときは再トライすれば大丈夫です。クラスターはアプリケーションの箱みたいなものです。
作成OKなら、こんな感じ

5-2 タスク定義を作成
タスク定義は本番環境の設計書です。CPUの割当、メモリサイズなどを指定します。環境変数なんかも設定できます。
左メニューからタスク定義をクリック

piseka-task という名前で、タスク定義を作成します。

ここで設定するコンテナ名はあとで使います

これ以外は、そのままで作成
5-3 サービスの作成
ついに、この手順を行うと、サービスが外部から見えるようになります。
先ほど作成したクラスターをクリックして、詳細を表示

サービスの作成をクリック
デプロイ設定で、先程作成した タスクを選択、リビジョンは(最新)がついていればOK
サービス名は、あとで利用するのでちゃんとつけましょう

ロード・バランシングの設定が必要です。これをやっておくことで、ECS Fargateのサービスを外部公開できるようになります。

特に赤字で示した部分は、しっかり確認して作成をクリック。
サービスの作成は、ちょっと時間がかかります。(数分)
作成がうまくいくと、ステータスアクティブなサービスが作成されます。

5-4 Security Group の確認
EC2を開きます

左メニューのロードバランサーをクリック

ロードバランサー名をクリックして、セキュリティをクリック

セキュリティグループIDをクリック

インバウンドルールを変更をクリック

ルールを追加でHTTP 80番に対して、すべての場所からのアクセスを許可します

この手順を行わないと、作成したALBに外部からアクセスすることができません。
5-5 動作確認
EC2を開きます

左メニューのロードバランサーをクリック

DNS名が出ているので、クリックしてコピー

手順5のチェックポイント
Hello Piseka!

価値が届きました

手順6 自動デプロイ
6-1 Github Actions を編集
stepsに3つ追加します。
- TASK定義を取得
- TASK定義のRevisionを変更
- ECSを新しいRevisionのTASK定義で更新
の流れを追加します。
name: deploy piseka
on:
push:
branches:
- main
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: latest
run: |
docker build -t $ECR_REGISTRY/${{ secrets.ECR_REPOSITORY }}:$IMAGE_TAG -f Dockerfile .
docker push $ECR_REGISTRY/${{ secrets.ECR_REPOSITORY }}:$IMAGE_TAG
echo "::set-output name=image::$ECR_REGISTRY/${{ secrets.ECR_REPOSITORY }}:$IMAGE_TAG"
- name: obtain task definition
run: |
aws ecs describe-task-definition --task-definition ${{ secrets.ECS_TASK_DEFINITION }} --query taskDefinition > task-definition.json
- name: Update task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: piseka-web
image: ${{ steps.build-image.outputs.image }}
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ secrets.ECS_SERVICE }}
cluster: ${{ secrets.ECS_CLUSTER }}
6-2 足りない secrets を追加
ECS_CLUSTER -> ECSクラスター名
ECS_SERVICE -> ECSサービス名
ECS_TASK_DEFINITION -> 作成したタスクの名前
最終的な secrets の様子

6-3 Github Actions の変更をpush
自動デプロイの確認のために src/index.php を変更しておく
<?php
echo "Hello Piseka! Auto Deployed!";
git add src/index.php
git add .github
git commit -m 'auto deploy'
git push origin main
手順6のチェックポイント
Actionsの正常終了

数分以内に自動デプロイが完了することを確認。変更した index.php がデプロイされていることを確認する。

ここまでのまとめ
CDは最初にやる
なにをおいてもCDまでやる
ここまで、最初にできていると、あとはコミット&PUSHするだけでよい。
価値提供のサイクルが最初に確定しているので安心。
アプリケーションをLaravelに変更
7-1 Laravelの準備
Dockerfile を編集して、Laravelに必要な zip拡張、composerを導入
FFROM php:8.4-apache-bullseye
RUN apt update \
&& apt install -y libzip-dev \
&& docker-php-ext-install zip
COPY /usr/bin/composer /usr/bin/composer
COPY src /var/www/src
ビルドする
docker compose build web
インストールの都合があるので、 compose.yml のmount設定を変えておく
services:
web:
build: .
ports:
- "80:80"
volumes:
- ./src:/var/www/src
コンテナを作り直す
docker compose down
docker compose up
7-2 Laravelをインストール
コンテナ内で作業
docker compose exec web bash
composer global require laravel/installer
cd /var/www
~/.composer/vendor/bin/laravel new laravel
cp -a laravel/. src/
これで、/var/www/src配下にlaravelが導入された
7-3 Apacheの設定変更
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/src/public
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Dockerfileの記述を変更
FROM php:8.4-apache-bullseye
RUN apt update \
&& apt install -y libzip-dev \
&& docker-php-ext-install zip
COPY /usr/bin/composer /usr/bin/composer
COPY ./000-default.conf /etc/apache2/sites-available/000-default.conf
COPY src /var/www/src
WORKDIR /var/www/src
RUN composer install
RUN cp .env.example .env \
&& php artisan key:generate \
&& php artisan migrate
RUN chown -R www-data:www-data /var/www/src
再度、コンテナを作り直す
docker compose build web
docker compose down
docker compose up
7-4 laravelの表示確認
ローカル環境

7-5 push
git add .
git commit -m 'laravel'
git push origin main
手順7のチェックポイント
albのアドレスでLaravelが表示されることを確認します。
お片付け
このまま環境を残してしまうと、お金がかかってしまうので、環境を削除しましょう。
- ECS Service 削除
- ECS Cluster 削除
- ECS タスク定義 -> 登録解除という扱い(クラスターが消えると、解除したものは消える...はず
- ECR コンテナレジストリを削除
- EC2 Security Gruops -> 80番ポートの許可設定を削除
- EC2 ALBロードバランサー
- EC2 ALBターゲット
- IAM ユーザー
- IAM ポリシー
Github リポジトリ -> 削除するかどうかは任意です。IAMユーザーを削除したあとはシークレットキーが漏洩しても、もはや問題にならない状態です。
気になる方は、Repository Secrets を削除しておきましょう。
Discussion