🧆

Amplify Gen2ならCDKで自由にカスタムできる。と思っていました。

2024/06/04に公開
6

結論から言うと、現時点でのAmplify Gen2はコンテナ(というかdockerコマンド)との相性が非常に悪いと思われます。dockerが使えないことで、PythonのLambdaをデプロイするのにも苦戦しました。

Amplify Gen2とは

https://aws.amazon.com/jp/blogs/news/introducing-amplify-gen2/

Amplify Gen2は、フルスタックのTypeScript開発体験を提供するAWS Amplifyの最新バージョンです。
従来のAmplifyよりも、開発体験が進化しており、特にバックエンド開発において以下のようなことができます。

  • CDKによるAWSリソースのデプロイが可能
  • AWS上にサンドボックス環境を容易に構築(と削除)が可能

ということなので、Gen2ならCDKでできることは拡張可能でしかもdeployが容易だと思っていました。が、ハマりました。

やろうとしたこと

PythonのライブラリであるFastAPIで作ったAPIをLambdaにDeployしようとしました。
AmplifyはTypeScriptで、FastAPIはPythonなので言語が違いますが、Amplify Gen2はCDKを書けるので問題ないだろうと思っていました。

FastAPIをLambdaで動かすために次の2案を考えました。

  1. APIをコンテナ化した上で、Lambda Web Adapterを使ってLambda上で動くようにする。
  2. Mangumを使ってFastAPIをLambda上で動くようにした上で、CDKのaws-lambda-python-alphaでデプロイする案

両方ともデプロイ時にdockerが必要になるのですが、AmplifyのCI/CD環境でdockerを使うことができずにAPIをデプロイすることができませんでした。
(1は当然dockerに依存しているとしても、2でも必要なのはびっくりしました。実行環境はFaaSですが、Pythonのパッケージを扱う環境を固定するためにdeploy時にdockerを使っているみたいです。)

回避策

最初はCI/CD環境でdockerコマンドを使えるようにできないか挑戦してみましたが、あきらめました。
以下の回避策により、なんとかFastAPIで作ったPythonのAPIをLambdaにDeployできました。

  1. Mangumを使ってLambda上でFastAPIを動くようにする
  2. こちらのドキュメントを参考に必要なライブラリを集めるスクリプトを書いて、deploy前に実行する
  3. CDKのlambda.Functionを使って、ソースコードと2で集めたライブラリをzipに固めてLambdaにDeployする

2の部分についてスマートではないので良い方法があれば差し替えをしたいですが、この方法ならdockerなしでPythonのLambdaをデプロイできました。

Amplify Gen1のコンテナAPIについて

Amplifyに詳しい方なら「AmplifyってGen1時代からコンテナAPIのデプロイできるよね?同じ方法でやればいいのでは?」と考えるかと思います。
私も多分できるのではないかと思います。ですが、Amplify Gen1のコンテナAPIはCodePipeline + CodeBuildを使っているのですよね。わざわざCDKでCodeBuild作ってAmplifyの環境からDeployを実行するのはちょっとツラいです。そこまでするなら最初からCDK+CodebBuildだけでいいのでは?と思ってしまいます。ということで最終手段としては考えられますができれば避けたく、今回はコンテナ自体を使わない方向に逃げました。

AmplifyのCI/CD環境について

「CI/CD環境を使うのがそんなに大変なら、とりあえず手動でDeployしちゃえばいいじゃない?ローカル環境ならDocker使えるのでしょ?」と思うかもしれません。
しかし、Amplify Gen2では本番DeployはCI/CD環境からのみ実施する思想で作られています。ローカル環境でデプロイを実行しようとすると、エラーで終了してしまいます。

$AWS_PROFILE=sandbox npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID

ampx pipeline-deploy

Command to deploy backends in a custom CI/CD pipeline. This command is not inten
ded to be used locally.

(略)

Error: It looks like this command is being run outside of a CI/CD workflow. To deploy locally use `amplify sandbox` instead.

ローカルからamplify sandboxで作った開発用のSandbox環境を無理やり本番で使ったり、環境変数CI=true設定してCI/CD環境に成り済ましてdeployする抜け道も考えられますが、好ましくはないですよね。

ですので、Amplify Gen2でCI/CD環境からDeployが通らないというのは、かなり致命的に困る状況になります。ローカルでの開発はできるけど、本番デプロイができないということですからね。

デプロイ時のログについて

Amplify Gen2のバックエンドは通常以下のコマンドでデプロイします。

npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID

このコマンドですが、困ったことにエラーが起きてもログが殆ど出ないです。しかも、AmplifyのCI/CDのログではバックエンドのビルドに失敗しても「Next.jsのSSRの設定を確認しよう」的なメッセージを出ます。私はエラーログが出てないこととこのメッセージに騙されてフロントエンドを作り直しました。
そういった悲劇を回避するためにバックエンドのdeployには--debugオプションをつけておくことをおすすめします。

npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID --debug

--debugをつけないとエラーログが出ないっておかしくないですか。。。?

Amplify Gen2で困ったことまとめ

今回Amplify Gen2を使ってみて困ったことをリストアップすると以下のようになります。

CI/CD環境でdockerコマンドが使えない

dockerコマンドが使えないのでECSやAppRunnerに活用できないのはもちろんですが、CDKは意外と他にもdockerに依存しているコンストラクトが多いので、コンテナを使ってないアプリでも思わぬところでハマります。PythonのLambdaとかがそうですね。

CI/CD環境からでないと本番デプロイができない

基本はCI/CD環境からしかデプロイしないようにする設計は賛成なのですが、なんだかんだで本番対応の時って、緊急で人がなんとかしないといけないことってありますよね。
何かあったときにローカル環境からデプロイできないのは、致命的な問題に成りかねないと思いました。

Amplify Gen2の情報が、まだ少ない

dockerコマンドが使えないって結構問題になりそうだと思うのですが、探しても全然情報が出てこなかったです。
更にいうと、Amplify Gen2のCI/CD環境のOSがAmazon Linux 2023なんですけどやっぱり情報が少ないですし、CI/CD環境を差し替えるとしてもAmplifyのカスタムイメージの情報も少ないです。つまり問題発生時の調査の難易度がかなり高いです。

結論

Amplify Gen2はCDKを書けるので拡張性が凄い!と思っていたのですが、結構罠がありそうです。ドキュメントに書いてあること以上のことには慎重になったほうが良さそうです。また、あくまでTypeScriptのフルスタック開発用のサービスなので、他の言語を使うときも注意したほうが良さそうです。

なお、今回は上手くいかなかったことを記事を書いたので後ろ向きな内容になっていますが、Amplify Gen2の開発体験自体はとても良いので、素直にTypeScriptでWebアプリを作る時はとても有用なサービスだと思っています。

追記(2024/09/03)

GitHub Actionsを使ってAmplify Gen2にコンテナでコンテナを使ったアプリをデプロイする記事を書きました。
https://zenn.dev/ncdc/articles/8da04fbca4105e

NCDCエンジニアブログ

Discussion

Atsushi KataokaAtsushi Kataoka

https://docs.aws.amazon.com/amplify/latest/userguide/custom-build-image.html
の手順でdocker使えるContainer Imageを設定してあげれば可能かもしれません。

(的外れなコメントでしたらすみません)

いばらきいばらき

コメントありがとうございます。

その通りなのですが、カスタムイメージで単純にdockerコマンドを使える状態にしても Docker デーモンが起動してくれなかったです。
難易度も高いし、とりあえずやりたいことはdockerなしでできたので、一旦諦めました。。。

Atsushi KataokaAtsushi Kataoka

カスタムイメージでdindできるDockerイメージを設定しても、Amplifyのビルド設定でDockerを特権モードで動かす方法が現状ないですね...

fossamagnafossamagna

dockerでイメージのビルドが必要な場合はカスタムパイプラインを使う方法でデプロイすることになると思います。
https://docs.amplify.aws/react/deploy-and-host/fullstack-branching/custom-pipelines/
ちょうど、そのパターンを試したときの資料も公開したのでご参考に。
https://speakerdeck.com/fossamagna/new-features-and-practical-use-cases-in-amplify-gen2?slide=15

いばらきいばらき

コメントと情報ありがとうございます。
やっぱりCodePilelineとかCodeCatalystとかGitHub Actions等の他のCI/CD環境を使わないとできないということになるのですね。今度カスタムパイプラインを試してみます。
しかし、そうなると現時点でコンテナが絡む場合の技術選定をする場合、バックエンドもAmplifyでカスタムパイプラインを使うかAmplifyを使わないで素のCDKでいくと判断するか悩ましいところですね。。。