8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ローカルでビルドしたものを package するときに --template-file オプションを付けるタイミング

Posted at

TL; DR

sam build でビルド先ディレクトリの出力先を指定した場合は、 sam package--template-file を指定しましょう。
そうでない場合(殆どが指定しないと思います)は、指定しない方が無難です。

はじめに

下記のような記事がありました。
私も最初は sam package--template-file オプションを付けて苦しめられていたため、参考になりました。

ローカルでビルドしたものをpackageするときは --template-file オプションはつけない - Qiita

では、逆に --template-file を指定するのはいつなのか、調べてみました。

フローの種類

sam buildsam package の挙動を知るには、ビルド手順を追うと分かりやすいです。
そこで、本章ではアプリケーションビルド手順を順次追っていきます。

SAM-CLIによるアプリケーションビルド手法は、次の4種類があります。

  1. deploy
  2. build -> deploy
  3. build -> package -> deploy
  4. 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
直接デプロイする際の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.jsonrequirement.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
ビルド後の.aws-sam/build/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
ビルド/パッケージング後のoutput-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

なお、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ゾッコンになっていきましょう!

参考

AWS サーバーレスアプリケーションモデル (AWS SAM) とは - AWS サーバーレスアプリケーションモデル

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?