2
0

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.

【ServerlessFramework】slsコマンドをコンテナ化する

Last updated at Posted at 2022-03-19

slsコマンドが環境に依存してしまうのがイヤで、slsコマンドをコンテナ化してみました。
サクッと作れるかと思いきや、意外と苦戦しました。。。
serverless-python-requirements プラグインを利用すると、dockerを利用してパッケージをビルドするのですが、こいつが曲者で、slsコマンド自体をコンテナ化しようとすると、コンテナ内からDockerコマンドが実行できてかつ、別コンテナでビルドした資材を参照できなくてはなりません。

いろいろ試行錯誤したので、まとめておこうかと思います。

一応、今回のソースはGitHubにpushしていますので、ソースの確認はこちらからどうぞ。

ディレクトリ構成

sls-sample/
| app/               // lambdaにデプロイするソースコード (今回はfastapiのwebアプリ)
| | __init__.py
| | main.py
| bin/
| | build.sh*        // イメージをビルドするスクリプト
| | sls.sh*          // コンテナを起動するコマンド
| docker/
| | sls/
| | | Dockerfile     // slsコンテナのDockerfile
| .dockerignore
| package-lock.json
| package.json
| requirements.txt   // lambdaの依存パッケージ定義(layerにする)
| serverless.yml

イメージ作成

コンテナ内でDockerコマンドを実行する方法は、コンテナ内でDockerデーモンを起動する「Docker in Docker(DinD)」と、docker.sockをマウントしてホスト側のDockerを操作する「Docker outside of Docker(DooD)」があります。DinDはさすがにオーバーヘッドが大きすぎるので、今回はDooDで作っていきます。
とはいえ、コンテナ内でDockerを利用する以上、Dockerのインストールは必須ですので、FROMイメージは公式のDinDのイメージ( docker:20.10.12-dind )を利用します。
このイメージは alpine:3.15 が元になっていますので apk コマンドで必要なパッケージをインストールしていけば良さそうです。

※ DinD, DooDはこちらの記事が非常に参考になりました。
コンテナからコンテナを操作する | 二畳半堂
Dockerコンテナ内からDockerを使うことについて

FROM docker:20.10.12-dind
RUN printenv
RUN apk update && apk add --no-cache nodejs npm
RUN npm install -g serverless@3.7.9
RUN mkdir /opt/sls
WORKDIR /opt/sls
COPY . .
RUN npm install

ビルドスクリプトを作ります。
※ 私はいつもオプションを忘れてしまうので、このくらいでもスクリプト化してしまいます。。。

bin/build.sh
#!/bin/bash
PROJECT_ROOT=$(cd $(dirname $0)/..; pwd)
cd $PROJECT_ROOT
docker build --rm -f docker/sls/Dockerfile -t sample-sls:latest .

コンテナの起動

コンテナの起動は少しポイントがあります。
基本は sls コマンドでコンテナを起動させればいいのですが、マウントするディレクトリが結構重要です。

  • -v ${HOME}/.aws:/root/.aws:ro
    ホスト側のAWSのcredentialsを参照できるようにします。
  • -v /root/.cache:/root/.cache
    serverless-python-requirementsによって別コンテナでビルドされた資材はホストの ${HOME}/.cache/serverless-python-requirements に配置されますので、slsコンテナからビルド資材を参照できるように /root/.cache をマウントします。
    ※ .serverlessディレクトリの中を見ると ~/.cache/serverless-python-requirements/... へのシンボリックリンクがあります。
  • -v /var/run/docker.sock:/var/run/docker.sock
    Dockerコマンドがホスト側のDocker環境で実行されるように、 docker.sock をマウントします。
  • -v ${PROJECT_ROOT}/app:/opt/sls/app
    lambdaにデプロイするディレクトリをマウントします。(複数ある場合はすべて)
  • -v ${PROJECT_ROOT}/requirements.txt:/opt/sls/requirements.txt
    pythonの依存パッケージ定義ファイルをマウントします。
  • -v ${PROJECT_ROOT}/serverless.yml:/opt/sls/serverless.yml
    ServerlessFrameworkの設定ファイルをマウントします。
bin/sls.sh
#!/bin/bash
PROJECT_ROOT=$(cd $(dirname $0)/..; pwd)
docker run -ti --rm \
  -v ${HOME}/.aws:/root/.aws:ro \
  -v /root/.cache:/root/.cache \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v ${PROJECT_ROOT}/app:/opt/sls/app \
  -v ${PROJECT_ROOT}/requirements.txt:/opt/sls/requirements.txt \
  -v ${PROJECT_ROOT}/serverless.yml:/opt/sls/serverless.yml \
  sample-sls:latest sls $*

ビルド & デプロイ手順

chmod 755 ./bin/*.sh

# イメージのビルド
./bin/build.sh

# デプロイ
./bin/sls.sh deploy

# ブラウザでAPIにアクセス
# https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/api/hello

参考

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?