Header image

クラッソーネの開発者がエンジニアリングに関することもそうでないことも綴っています!

AWS Amplifyの手動デプロイについて検証しました

AWS Amplifyの手動デプロイについて検証しました

はじめに

こんにちは。年に一度は必ず『惑星のさみだれ』を読み返してそのたびに感涙している小木(@jacoyutorius)です。

私の所属する開発チームでは今後開発する施主さん向けの新機能について、Figmaでデザインされたコンポーネントとのシームレスな連携を重視して Reactで実装する方針となりました。

そして、そのReactアプリケーションをデプロイするのには AWS Amplify を使うことを検討しています。

AWS Amplifyとは?

AWS版の NetlifyVercel といえば早いでしょうか。フロントエンドWebアプリケーションを一撃でデプロイできる仕組みです。
デプロイだけでなく、ファイルアップロード や ユーザー認証、地図など、AWSのサービスを簡単にアプリケーションへ組み込むためのライブラリが豊富に提供されています。

Amplifyの手動デプロイについて

Amplifyの一般的な設定では、Githubリポジトリと接続し、リポジトリへのpushをフックすることで AmplifyによるCI/CDを実行します。
本番用ブランチにプルリクエストをマージすると本番環境が自動的に更新される、という感じですね。

これ自体はとても便利な機能なのですが、私たちの場合、本番用ブランチをstaging 環境へデプロイし、その後に人手による承認ステージを経てから本番環境にデプロイする、というCodePipelineの仕組みが既に運用されているため、Amplifyのこの便利な機能が逆に邪魔になってしまうのでした。

ということで、今回はAmplifyをGithubリポジトリと接続するのではなく、手動デプロイオプションを利用することで既存のデプロイパイプラインに組み込めないか?と思い立ち調査してみました。

検証用のReactアプリをビルド

まず検証用のアプリをビルドします。

手元に AWSが先日公開したCloudscape (https://cloudscape.design/) をざっくり組み込んだだけの Reactアプリがあったのでそれを使っています。

$ yarn build
yarn run v1.22.10
$ react-scripts build
Creating an optimized production build...

File sizes after gzip:

  82.61 kB  build/static/js/main.caa05ebb.js
  31.86 kB  build/static/css/main.d2a0b07d.css

The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.
You may serve it with a static server:

  npm install -g serve
  serve -s build

build ディレクトリが生成されました。

$ tree build
build
├── asset-manifest.json
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
├── robots.txt
└── static
    ├── css
    │   ├── main.d2a0b07d.css
    │   └── main.d2a0b07d.css.map
    └── js
        ├── main.caa05ebb.js
        ├── main.caa05ebb.js.LICENSE.txt
        └── main.caa05ebb.js.map

3 directories, 12 files

ドキュメント に以下のように注記されているので気をつけましょう。

zip フォルダを作成するときは、最上位フォルダではなく、ビルド出力の内容を圧縮してください。
たとえば、ビルド出力で「build」または「public」という名前のフォルダが生成される場合は、
まずそのフォルダに移動し、すべてのコンテンツを選択し、そこから圧縮します。

ソースを含むディレクトリまでzipに含まれるとデプロイに失敗するようです(Reactで言えば、build ディレクトリを除き、その配下のファイルのみが圧縮されるようにします)

$ cd build

$ zip -r cloudscape-sandbox-develop *
  adding: asset-manifest.json (deflated 61%)
  adding: favicon.ico (deflated 11%)
  adding: index.html (deflated 45%)
  adding: logo192.png (deflated 1%)
  adding: logo512.png (deflated 0%)
  adding: manifest.json (deflated 53%)
  adding: robots.txt (deflated 10%)
  adding: static/ (stored 0%)

S3にzipファイルをアップロードする

今回は手作業で全てデフォルト設定のままS3バケットを作ってzipファイルをアップロードしました。アップロード時のオプションも全てデフォルトのままです(これがいけなかった。後述します)。

S3_Management_Console_と_ogiyuto_MacBook-Pro___Work_reactjs_cloudscape-sandbox_と_Amplifyの手動デプロイ.png

Amplifyの手動デプロイ設定

AWSのマネージメントコンソールよりAWS Amplifyを開き、「新しいアプリケーション」⇒ 「ウェブアプリケーションをホスト」を選択。

以下のようなダイアログが表示されます。今回はソース管理と連携させず、手動でデプロイしたいので「Gitプロバイダーなしでデプロイ」を選択。

AWS_Amplify_console_と_Amplifyの手動デプロイ.png

アプリケーション名・環境名・バケット・zipファイル名を入力。
環境名はデプロイ後に発行されるendpointに含まれます。

AWS_Amplify_console_と_ogiyuto_MacBook-Pro___Work_reactjs_cloudscape-sandbox_build_と_ダウンロード.png

ファイル数が少ないこともあり、数秒でデプロイに成功しました 👏

AWS_Amplify_console.png

発行されたendpointにアクセスすると以下のように。先程入力した環境名がURLに含まれているのがわかるかと思います。

https://develop.d3uyau3xug1qwi.amplifyapp.com/
(Basic認証は test/password で通れます)

React_App.png

ちなみに手動デプロイでもBasic認証をかけることができました。

ログイン_と_https___develop_d3uyau3xug1qwi_amplifyapp_com.png


トラブルシューティングなど

デプロイに成功するまでに一箇所ハマったポイントがあります。

「Please enable AccessControlList on your S3 bucket before continuing」

「保存してデプロイ」ボタンを押すと以下のようなエラーメッセージが表示されました。

AWS_Amplify_console_と_ogiyuto_MacBook-Pro___Work_reactjs_cloudscape-sandbox_と_Amplifyの手動デプロイ-2.png

S3バケットのACLが無効になっているのが原因のようです。S3バケットをデフォルト値のまま作ったため、ACLが無効になっていたのでしょう。

ACLを有効化してから再度デプロイします。

jacoyutorius-amplify-manual-deploy_-_S3_bucket.png

jacoyutorius-amplify-manual-deploy_-_S3_bucket-2.png

ACLが無効になっている場合、バケット内のオブジェクトの所有者はアカウントにのみに限定されてしまいます。そうなるとAmplifyがバケットのオブジェクトを読めないのでデプロイできないのですね。

ACLがデフォルトOffなんてそんな機能あったっけ?と思ったんですが、調べたら昨年リリースされた機能のようですね。
Amazon S3 Object Ownership で、S3 内のデータのアクセス管理をシンプル化するためのアクセスコントロールリストの無効化が可能に

S3トリガーを使ったAmplifyアプリの更新

さて、S3へ圧縮したReactのソースコードをアップロードすることでAmplifyへデプロイができたわけですが、アプリケーションの更新を適用するにはどうしたらよいか?

1つはマネージメントコンソールにて、更新するファイルを指定する方法です。
初回デプロイ時と同様のダイアログからファイルのアップロード方法を選択することで、再デプロイが行われます。

AWS_Amplify_console.png

とはいえ、毎回マネージメントコンソールを開いてデプロイするのは手間ですし、冒頭でお話したように、今回は既存のパイプラインへの組み込みを目的としています。

ということで、もう1つの方法を採ります。S3トリガーを利用して S3へのファイルアップロードをフックにAmplifyへのデプロイをすることができます。

Deploy files stored on Amazon S3, Dropbox, or your Desktop to the AWS Amplify Console

AWS SDKで以下のようなコードを実行することで Amplifyに再デプロイを指示することができるのですね。

amplify.startDeployment({
  appId,
  branchName,
  sourceUrl: `s3://${Bucket}/${objectKey}`
})

基本的には記事通りに Lambdaを作成して適宜必要な権限を付与することで実装できました。
強いて言えばスクリーンショットが古いので、そのまま参考にするといささか操作に迷うということでしょうか。

少し補足します。
Lambdaが作成されたあと、「設定」のタブに記載されている実行ロールのリンクをクリックすることで、このLambdaを実行するためのIAMロールの編集ページを開くことができます。

s3-amplify-console_-_Lambda.png

AWSLambdaBasicExecutionRole がすでに作成されているので、それに加えてS3の参照とAmplifyの実行権限を付与します。

元の記事では S3FullAccess に加え、Amplifyについてもほぼ全ての権限を与えていますが、本番運用する場合には対象リソースを指定したり付与する権限を絞ったりしたほうが良さそうです。

IAM_Management_Console.png

IAM_Management_Console.png

ともあれ、これらの設定をすることで S3へのzipファイルアップロード後に以下のように2回目のデプロイが完了したことが確認できました。

AWS_Amplify_console.png

AWS_Amplify_console.png

残念ながらGithubと接続した場合に使える、以前のバージョンの再デプロイ機能は使えない様子でした。S3のバージョニング機能を使えば実現できそうな気がするので、いずれ対応してほしいところですね。
(↓はGithubと接続してデプロイした別アプリのデプロイ画面です)
AWS_Amplify_console.png

終わりに

Amplifyの手動デプロイの仕組みについてある程度理解できました。
これを踏まえて弊チームのデプロイパイプラインにAmplifyを組み込むとするとざっくり以下のようなイメージになります。

デプロイイメージ

実はAmplifyはサービスが登場したころからプライベートの開発でずっと使っており、なんならAWSで一番好きなサービスです。
思い入れが強いので逆に選択肢から外していたのですが、今回の検証で十分に本番利用に足ることがわかってきました。本番利用することでさらなる知見が得られそうで期待しています。

さて、クラッソーネではプロダクトとチームの双方をより良く改善していけるエンジニアを募集中です!
Reactが好きな方、Amplifyでガッツリサービス運用してみたいかたのご連絡お待ちしております。

https://www.crassone.co.jp/recruit/engineer/


静岡県浜松市のアプリケーションデベロッパー。ITコミュニティやシビックテックにも興味があります。