TL; DR
sam build
でビルド先ディレクトリの出力先を指定した場合は、 sam package
で --template-file
を指定しましょう。
そうでない場合(殆どが指定しないと思います)は、指定しない方が無難です。
はじめに
下記のような記事がありました。
私も最初は sam package
に --template-file
オプションを付けて苦しめられていたため、参考になりました。
ローカルでビルドしたものをpackageするときは --template-file オプションはつけない - Qiita
では、逆に --template-file
を指定するのはいつなのか、調べてみました。
フローの種類
sam build
と sam package
の挙動を知るには、ビルド手順を追うと分かりやすいです。
そこで、本章ではアプリケーションビルド手順を順次追っていきます。
SAM-CLIによるアプリケーションビルド手法は、次の4種類があります。
- deploy
- build -> deploy
- build -> package -> deploy
- build -> package -> publish
各フローについて、それぞれ説明します。
今回は、Node.jsによるLambdaアプリケーションのSAMテンプレートファイルを用いて説明します。
そのため、一部に npm コマンドの比喩が登場します。
Node.js固有の問題は無いと思うので、LambdaランタイムがPythonの場合はpipと読替えるなど、よしなに読んでください。
deploy
直接デプロイする手法です。
デプロイとは、テンプレートファイルで指定したディレクトリを直接SAMアプリケーション(CloudFormationスタック)として生成することです。
そのため、 --template-file
で指定したテンプレートファイルの中身にアプリケーションリソースのURLを指定している必要があります。
sam deploy --template-file template.yaml
application/
|- sample-app/
| |- node_modules/*
| |- package.json
| |- index.js
|
|- template.yaml
Resources:
DirectlyDeploymentFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./sample-app/
Handler: index.handler
Runtime: nodejs12.x
Description: ローカルの sample-app/index.js ファイルにおける index.handler をAWS Lambdaに展開
直接デプロイする際は、テンプレートファイルの CodeUri
で指定しているディレクトリ内のソースコードを実行できる必要があります(npm run
などの実行スクリプトが動作可能な状態である必要がある、という意味です)。
依存ライブラリなどがある場合は、事前に npm install
などでインストールしておきましょう。
sam deploy - AWS サーバーレスアプリケーションモデル
build -> deploy
ビルドしてからデプロイする手法です。
ビルドとは、 テンプレートファイル自身、および、テンプレートファイルの CodeUri
で指定しているディレクトリをコピーした「ビルド先ディレクトリ」の2つを生成し、生成先ディレクトリ内の package.json
や requirement.txt
を再帰的に探し、 npm install
を実施することです。
既定では、 .aws-sam/build/
ディレクトリ内にコピーしますが、 --build-dir
オプションで出力先を変更できます。
デプロイ時のテンプレートファイルは、既定では .aws-sam/build/
ディレクトリ内の template.yaml
または template.yml
ファイルを取込みます。
そのため、 --template-file
での指定は必要ありません。
しかも、 .aws-sam/build/
ディレクトリ内のテンプレートファイルに書いてある CodeUri
は、自動で書換えられます。
sam build
sam deploy
application/
|- sample-app/
| |- package.json
| |- index.js
|
|- .aws-sam/
| |- build/
| |- DeploymentBuildedFunction/
| | |- node_modules/*
| | |- package.json
| | |- index.js
| |
| |- template.yaml
|
|- template.yaml
Resources:
DeploymentBuildedFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: DeploymentBuildedFunction # 書換えられている
Handler: index.handler
Runtime: nodejs12.x
Description: ローカルの .aws-sam/build/index.js ファイルにおける index.handler をAWS Lambdaに展開
コピー先ディレクトリ .aws-sam/build/
内で npm install
をするため、 sample-app/
ディレクトリ内での npm install
は必要ありません。
sam build - AWS サーバーレスアプリケーションモデル
build -> package -> deploy
ビルド/パッケージングしてデプロイする手法です。
パッケージングとは、作業中PC(SAM-CLIを実行しているPCのこと)のソースコードを指定したS3バケットにパッケージングしてアップロードすることです。
そして、指定したS3バケットのURLを示すように CodeUri
を書換えたテンプレートを出力します。
なぜか既定では標準出力に出力しますが、 --output-template-file
オプションでファイル出力ができます。
デプロイする際は、パッケージングで出力されたテンプレートファイルを指定します。
sam build
sam package \
--s3-bucket UploadedApplication \
--output-template-file output-template.yaml # 出力ファイルを指定する
sam deploy --template-file output-template.yaml # sam packageコマンドで出力されたファイルを指定する
application/
|- sample-app/
| |- package.json
| |- index.js
|
|- .aws-sam/
| |- build/
| |- DeploymentPackagedFunction/
| | |- node_modules/*
| | |- package.json
| | |- index.js
| |
| |- template.yaml
|
|- output-template.yaml
|- template.yaml
Resources:
DeploymentPackagedFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://UpploadedApplication/xxxxxxxx # --s3-bucket オプションで指定したディレクトリ先のランダムな名前のパッケージファイル
Handler: index.handler
Runtime: nodejs12.x
Description: S3バケットのパッケージファイルにおける index.handler をAWS Lambdaに展開
前節を読んだ方はお気づきかと思いますが、パッケージングする際の入力テンプレートファイルは、 .aws-sam/build/
ディレクトリ内のテンプレートファイルです。
また、パッケージング対象は、上記で(明示的または暗黙的に)指定したテンプレートファイルの CodeUri
で指定しているディレクトリです。
パッケージファイルにテンプレートファイル自身は含まれません。
sam package - AWS サーバーレスアプリケーションモデル
build -> package -> publish
ビルド/パッケージングして発行(パブリッシュ)する手順です。
発行(パブリッシュ)とは、SAR (Serverless Application Repository) と呼ばれる公開可能なアプリケーションリポジトリにテンプレートファイルを登録することです。
--template-file
オプションで指定したテンプレートファイルを、AWSのクラウドサービスに登録するため、ローカルパスを指定しているパッケージング前のテンプレートファイルではなく、S3バケットを指定しているパッケージング後のテンプレートファイルを指定する必要があります。
sam build
sam package \
--s3-bucket UploadedApplication \
--output-template-file output-template.yaml
sam publish --template-file output-template.yaml
- sam publish - AWS サーバーレスアプリケーションモデル
- AWS Serverless Application Repository(サーバーレスアプリを検索、デプロイ、公開)| AWS
- AWS Serverless Application Repository とは - AWS Serverless Application Repository
なお、2020年6月時点では、SARに発行したアプリケーションをデプロイする場合、AWSマネジメントコンソール上で手動デプロイするか、AWS-CLIを使う必要があります。
sam publish
した際にアプリケーションARNを出力してくれるため、 aws serverlessrepo
コマンドでデプロイすれば良いです。
本記事では話がズレてしまうため、詳細は省略します。
アプリケーションをデプロイする方法 - AWS Serverless Application Repository
ローカルでビルドしたものを package するときに --template-file
オプションを付けるタイミング
本題です。
結論を先に言ってしまうと、ローカルでビルドしたものを package するときに --template-file
オプションを付けるタイミングとは、__ビルド先のディレクトリを変更した場合__です。
ビルドの振舞いが理解できれば、パッケージングの振舞いも理解できると思います。
sam build
は、既定ではテンプレートファイルの CodeUri で指定しているディレクトリを .aws-sam/build/
ディレクトリにコピーすると書きました。
また、 sam package
は、既定では .aws-sam/build/
ディレクトリ内のテンプレートファイルを呼出してパッケージファイルをS3にアップロードすると書きました。
つまり、 sam build
でビルド先(コピー先)ディレクトリを --build-dir
オプションで書換えた場合、 sam package
でテンプレートファイルを --template-file
で指定する必要があります。
sam build \
--build-dir builded-sample-app/ # ここで出力先を指定すると
sam package \
--s3-bucket UploadedApplication \
--template-file builded-sample-app/template.yaml \ # ここで入力先を指定する必要がある
--output-template-file output-template.yaml
sam deploy --template-file output-template.yaml
application/
|- sample-app/
| |- package.json
| |- index.js
|
|- builded-sample-app/
| |- DeploymentPackagedFunction/
| | |- node_modules/*
| | |- package.json
| | |- index.js
| |
| |- template.yaml
|
|- output-template.yaml
|- template.yaml
次のような場合に使えると思います。
- 複数のアプリケーションを1つのディレクトリ内でデプロイしたい
- ネステッドスタックを作りたい(ビルドを2回する必要がある)
おわりに
SAM-CLIの挙動は、チュートリアルからでは全く理解できませんが、少しずつ理解していくと意外とシンプルです。
Serverlessの時代、SAMを使ってAWSゾッコンになっていきましょう!