AWS Amplifyの手動デプロイについて検証しました
はじめに
こんにちは。年に一度は必ず『惑星のさみだれ』を読み返してそのたびに感涙している小木(@jacoyutorius)です。
私の所属する開発チームでは今後開発する施主さん向けの新機能について、Figmaでデザインされたコンポーネントとのシームレスな連携を重視して Reactで実装する方針となりました。
そして、そのReactアプリケーションをデプロイするのには AWS Amplify を使うことを検討しています。
AWS Amplifyとは?
AWS版の NetlifyやVercel といえば早いでしょうか。フロントエンド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ファイルをアップロードしました。アップロード時のオプションも全てデフォルトのままです(これがいけなかった。後述します)。
Amplifyの手動デプロイ設定
AWSのマネージメントコンソールよりAWS Amplifyを開き、「新しいアプリケーション」⇒ 「ウェブアプリケーションをホスト」を選択。
以下のようなダイアログが表示されます。今回はソース管理と連携させず、手動でデプロイしたいので「Gitプロバイダーなしでデプロイ」を選択。
アプリケーション名・環境名・バケット・zipファイル名を入力。
環境名はデプロイ後に発行されるendpointに含まれます。
ファイル数が少ないこともあり、数秒でデプロイに成功しました 👏
発行されたendpointにアクセスすると以下のように。先程入力した環境名がURLに含まれているのがわかるかと思います。
https://develop.d3uyau3xug1qwi.amplifyapp.com/
(Basic認証は test/password で通れます)
ちなみに手動デプロイでもBasic認証をかけることができました。
トラブルシューティングなど
デプロイに成功するまでに一箇所ハマったポイントがあります。
「Please enable AccessControlList on your S3 bucket before continuing」
「保存してデプロイ」ボタンを押すと以下のようなエラーメッセージが表示されました。
S3バケットのACLが無効になっているのが原因のようです。S3バケットをデフォルト値のまま作ったため、ACLが無効になっていたのでしょう。
ACLを有効化してから再度デプロイします。
ACLが無効になっている場合、バケット内のオブジェクトの所有者はアカウントにのみに限定されてしまいます。そうなるとAmplifyがバケットのオブジェクトを読めないのでデプロイできないのですね。
ACLがデフォルトOffなんてそんな機能あったっけ?と思ったんですが、調べたら昨年リリースされた機能のようですね。
Amazon S3 Object Ownership で、S3 内のデータのアクセス管理をシンプル化するためのアクセスコントロールリストの無効化が可能に
S3トリガーを使ったAmplifyアプリの更新
さて、S3へ圧縮したReactのソースコードをアップロードすることでAmplifyへデプロイができたわけですが、アプリケーションの更新を適用するにはどうしたらよいか?
1つはマネージメントコンソールにて、更新するファイルを指定する方法です。
初回デプロイ時と同様のダイアログからファイルのアップロード方法を選択することで、再デプロイが行われます。
とはいえ、毎回マネージメントコンソールを開いてデプロイするのは手間ですし、冒頭でお話したように、今回は既存のパイプラインへの組み込みを目的としています。
ということで、もう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ロールの編集ページを開くことができます。
AWSLambdaBasicExecutionRole
がすでに作成されているので、それに加えてS3の参照とAmplifyの実行権限を付与します。
元の記事では S3FullAccess
に加え、Amplifyについてもほぼ全ての権限を与えていますが、本番運用する場合には対象リソースを指定したり付与する権限を絞ったりしたほうが良さそうです。
ともあれ、これらの設定をすることで S3へのzipファイルアップロード後に以下のように2回目のデプロイが完了したことが確認できました。
残念ながらGithubと接続した場合に使える、以前のバージョンの再デプロイ機能は使えない様子でした。S3のバージョニング機能を使えば実現できそうな気がするので、いずれ対応してほしいところですね。
(↓はGithubと接続してデプロイした別アプリのデプロイ画面です)
終わりに
Amplifyの手動デプロイの仕組みについてある程度理解できました。
これを踏まえて弊チームのデプロイパイプラインにAmplifyを組み込むとするとざっくり以下のようなイメージになります。
実はAmplifyはサービスが登場したころからプライベートの開発でずっと使っており、なんならAWSで一番好きなサービスです。
思い入れが強いので逆に選択肢から外していたのですが、今回の検証で十分に本番利用に足ることがわかってきました。本番利用することでさらなる知見が得られそうで期待しています。
さて、クラッソーネではプロダクトとチームの双方をより良く改善していけるエンジニアを募集中です!
Reactが好きな方、Amplifyでガッツリサービス運用してみたいかたのご連絡お待ちしております。