🐥

100分で本番デプロイ!Laravelで作るWebアプリケーション作成の作業手順書全公開

2025/02/08に公開
4

事前チェック

  1. Docker入ってますか!? -> docker -v
  2. Git入ってますか? -> git -v
  3. Githubのアカウント持ってますか? -> ログインしておきましょう
  4. 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

ブラウザで確認

http://localhost

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つ追加します。

  1. TASK定義を取得
  2. TASK定義のRevisionを変更
  3. 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 --from=composer:latest /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 --from=composer:latest /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 を削除しておきましょう。

4

Discussion