Edited at

serverless.ymlのちょっと便利な書き方 with serverless-offline on docker

More than 1 year has passed since last update.


やりたかったこと


  • serverless.ymlのprovider.environmentにはローカル環境とデプロイする環境で別の値を入れたい


    • デプロイする環境では同yaml内で作成したリソースのID等をRef:して定義したい



      • resourcesはcloudformationなのでRef:等が使えるのは知ってる


      • provider.environmentとかでもRef:したいんだけどできるのかな?



    • ローカル環境ではコンテナの環境変数を参照して定義したい


      • ローカルは serverless-offline on docker な環境

      • そこではリソースの作成は行われないので、コンテナの環境変数を読む必要があった






結果



  • Ref:できた



  • 環境変数を読む / Ref:するに関して


    • ステージごとにprovider.environmentを制御することで実現できた

    • デプロイ時にはRef:の値を利用し、コンテナのserverless-offlineでは環境変数を読み込む




serverless.yml

ちょこちょこ情報は削ってますが、こんな感じのyamlになります

cognitoのリソースを作成している


serverless.yml

provider:

name: aws
runtime: nodejs8.10
region: ${env:AWS_REGION}
stage: ${opt:stage, self:custom.defaultStage}
environment:
COGNITO_DOMAIN: ${env:COGNITO_DOMAIN}
COGNITO_CLIENT_ID: ${self:custom.cognito.clientId.${self:provider.stage}}
COGNITO_USER_POOL_ID: ${self:custom.cognito.userPoolId.${self:provider.stage}}
vpc:
securityGroupIds:
- ${env:SECURITY_GROUP_ID}
subnetIds:
- ${env:SUBNET_ID_0}
- ${env:SUBNET_ID_1}
iamRoleStatements:
- Effect: "Allow"
Action:
- "ec2:CreateNetworkInterface"
- "ec2:DescribeNetworkInterfaces"
- "ec2:DeleteNetworkInterface"
- "cognito-idp:*"
Resource:
- "*"

custom:
defaultStage: dev
cognito:
clientId:
dev:
Ref: UserPoolClient
local: ${env:COGNITO_CLIENT_ID}
userPoolId:
dev:
Ref: UserPool
local: ${env:COGNITO_USER_POOL_ID}

functions:
# 〜略〜

resources:
Resources:
UserPool:
Type: AWS::Cognito::UserPool
Properties:
# 〜略〜
UserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
# 〜略〜
UserPoolId:
Ref: UserPool



解説

コンテナで叩くコマンド

$ serverless offline --stage local


serverless.ymlの状態

COGNITO_CLIENT_ID: ${env:COGNITO_CLIENT_ID}

COGNITO_USER_POOL_ID: ${COGNITO_USER_POOL_ID}

デプロイする時のコマンド

$ serverless deploy


serverless.ymlの状態

COGNITO_CLIENT_ID:

Ref: UserPoolClient
COGNITO_USER_POOL_ID:
Ref: UserPool



  • opt:stage


    • コマンドラインオプションの --stage で指定した値




  • self:custom.defaultStage


    • コマンドラインオプション --stage の指定がなかった場合、custom.defaultStageがデフォルト値となる




  • \${self:custom.cognito.clientId.${self:provider.stage}}


    • ${self:provider.stage} = dev または --stageの引数

    • つまり今回の場合、custom.cognito.clientId.dev または custom.cognito.clientId.local



ちなみに



  • self


    • このserverless.yml自身を指す




  • custom


    • 独自定義した値




docker-compose.yml


docker-compose.yml

version: '3'

services:
slsdb:
image: mariadb:10.2
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --skip-character-set-client-handshake
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD
- MYSQL_DATABASE
slsapp:
build: .
command: npx serverless offline --stage local --host 0.0.0.0 --port 3000
volumes:
- .:/application
- /application/node_modules
ports:
- "3000:3000"
depends_on:
- slsdb
environment:
- SECURITY_GROUP_ID
- SUBNET_ID_0
- SUBNET_ID_1
- MYSQL_ROOT_PASSWORD
- MYSQL_DATABASE
- MYSQL_USER
- MYSQL_HOST
- MYSQL_PORT
- COGNITO_CLIENT_ID
- COGNITO_USER_POOL_ID
- COGNITO_DOMAIN


解説

コンテナを立ち上げ時、コマンド npx serverless offline --stage local --host 0.0.0.0 --port 3000 を実行する

--stage localオプションを指定しているため、serverless.ymlで記載した通り、serverless.ymlではlocalの値を使用してserverless-offlineが起動する

また、AWSリソースの作成は行われないため、一度デプロイしたあと、COGNITO_CLIENT_ID等の値をコンテナの環境変数に設定しないといけないところは注意。