AWS SAMをローカルDockerコンテナ上で動かす


目標

前回のAWS SAM CLIによるサーバレス環境構築に引き継ぎ、SAM環境構築で直接にローカルPCにインストールではなく、Docker内に入れます。Docker導入の良いところは、個人開発環境のパッケージのバージョンを統一できるメリットがもちろん、MysqlやElasticSearchなどの導入も迅速できます。

ちなみに、エキサイトの「開発現場でAWSサーバーレスを導入しました」記事も紹介しました。

前提

入門編に紹介している知識を把握していることが前提です。また、Dockerの基礎知識があり、ローカルPCにDockerインストールしておく必要。

構築

アプリケーションのひな形生成

初回だけ雛形生成が必要なので、前回みたいsam init実行します。

$ sam init \
    --runtime python3.8 \
    --name excite-serverless-project \
    --app-template hello-world

excite-serverless-projectプロジェクトが作成されました。

ディレクトリ構造を再編

最終的にこのようなフォルダー構成を作ります

├── README.md
├── __init__.py
├── bin
│   ├── build.sh
│   └── deploy.sh
├── docker
│   └── Dockerfile
├── docker-compose.yml
├── src
│   ├── hello_world
│   │   ├── __init__.py
│   │   ├── app.py
│   │   └── requirements.txt
│   └── template.yaml
└── tests
    ├── __init__.py
    └── unit
        ├── __init__.py
        └── test_handler.py

とりあえず、Events不要なので削除します

$ rm -rf events/

実際にAPIエンドポイントが複数あるので、もう1段を下げます

$ mkdir src
$ mv hello_world template.yaml src

Docker環境構築

  • AWSの認証設定 AWSへデプロイのため、アクセスキーIDとシークレットキー設定が必要です。
$ mkdir .aws

保存フォルダーだけ先に作成しておきます。

  • docker管理フォルダー作成
$ mkdir docker

Dockerfileファイル作成、以下の内容を追加します

FROM python:3.8

# create local bin directory
RUN mkdir -p /root/.local/bin
ENV PATH $PATH:/root/.local/bin

# Install awscli and aws-sam-cli
RUN pip install -U pip setuptools wheel --no-cache-dir && \
  pip install pipx --no-cache-dir && \
  pipx install virtualenv && \
  pipx install pipenv && \
  pipx install awscli==1.* && \
  pipx install aws-sam-cli==1.9.0

WORKDIR /usr/src

最後にdocker-compose.yml作成します

version: "3"

services:
  sam_instance:
    container_name: excite-sam-instance
    image: excite-sam-instance
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    networks:
      - excite-sam-network
    volumes:
      - .:/usr/src
networks:
  excite-sam-network:
    driver: bridge

コマンド省略化のために、bashファイルにまとめる

まず、スクリプト保存フォルダーを作成します

$ mkdir bin

build.shファイル作成、以下の内容を追加します。

#!/bin/bash
set -o errexit

# aws profile
echo -n "AWS_ACCESS_KEY_ID:"
read -r AWS_ACCESS_KEY_ID
echo -n "AWS_SECRET_ACCESS_KEY:"
read -r AWS_SECRET_ACCESS_KEY

# aws credentials
echo "[default]" > .aws/credentials
echo "aws_access_key_id = $AWS_ACCESS_KEY_ID" >> .aws/credentials
echo "aws_secret_access_key = $AWS_SECRET_ACCESS_KEY" >> .aws/credentials

# aws config
echo "[default]" > .aws/config
echo "output = json" >> .aws/config
echo "region = ap-northeast-1" >> .aws/config

# build docker
docker-compose build "${@}"

次にdeploy.shファイル作成、以下の内容を追加します。

#!/bin/bash
set -o errexit

TEMPLATE_FILE=$1
DOCKER_IMAGE_NAME=excite-sam-instance
STACK_NAME=excite-api-lambda-deploy-stack
S3_BUCKET_NAME=excite-api-lambda-deploy-bucket

# build SAM template
docker run \
  -v $(pwd):/usr/src \
  -v $(pwd)/.aws:/root/.aws --rm $DOCKER_IMAGE_NAME \
  sam build -t "$TEMPLATE_FILE"

# SAM deploy
docker run \
  -v $(pwd):/usr/src \
  -v $(pwd)/.aws:/root/.aws --rm $DOCKER_IMAGE_NAME \
  sam deploy --template-file .aws-sam/build/template.yaml --stack-name "$STACK_NAME" \
    --s3-bucket "$S3_BUCKET_NAME" --capabilities CAPABILITY_NAMED_IAM  --no-fail-on-empty-changeset

# remove unnecessary folder
rm -rf .aws-sam

AWSへデプロイしてみる

まず、ビルド実施

$ ./bin/build.sh

個別でテンプレートをAWSへデプロイ

$ ./bin/deploy.sh src/template.yaml 

API Gatewayのアクセスポイントでアクセスしてみる

$ curl https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello
{"message": "hello world"}

と返ってくれば成功です。

最後に

実際の開発現場でdockerが非常に便利です。ローカルでAPIの開発・デバッグ・デプロイの一連作業ができます。次の単体テスト編は実際にコードを書いて、単体テストを実施してみます。

エキサイト株式会社では随時に仲間を募集しております。