いつか誰かのあら^〜便利になることを祈ってます。僕です。
あら便利カレンダー2018
概要
serverless framework(併せてserverless offline)を用いたlambdaの開発を行うにあたり、ローカル開発環境の準備が必要だった。
DBはmariadb(mysql)。
そんなローカル開発環境をdockerコンテナで用意してみた。
構成
以下のモジュールを突っ込んだコンテナをdocker composeで構築する。
- nodeコンテナ
- typescript
- serverless framework
- serverless offline
- ts-loader
- serverless webpack
- mysql
- その他諸々
- mariadbコンテナ
- こっちは特にない
諸々のバージョン
大事そうなとこだけ抜粋。
- node: 8.11.3
- mariadb: 10.2.16
- typescript: 2.9.2
- webpack: 4.16.0
- serverless webpack: 5.2.0
コンテナにするメリット
- dockerさえあれば開発もデプロイもできる
- いつまでもあのころのmacのまま、環境汚染しない
- デプロイ等で
slsなコマンドを叩く時もコンテナ内で(コンテナ経由で)実行する
- コンテナ使うと環境の共有も楽
- VM重すぎるよぉ😫みたいなつらみもない
引き続き頑張ってdockerおじさん目指したい次第。
ディレクトリ構造
sample_project/
├ app/
│ └ tsのいろいろ
├ Dockerfile
├ docker-compose.yml
├ package.json
├ webpack.config.js
├ tsconfig.json
└ serverless.yml
みたいな感じ。
Dockerfile
アプリを載せるnodeのコンテナイメージを作るのに用意した。
railsとかだと依存物が結構あるので、apk add でパッケージの追加が必要だった。
みんな大好きnokogiriとかあのへんの兼ね合いだったかな
でも、nodeだとdocker hubにあるイメージのままほとんど手を加えてない。楽。
FROM node:8-alpine
RUN mkdir /application
WORKDIR /application
COPY package.json ./
RUN \
set -x \
&& npm install
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 --host 0.0.0.0 --port 3000
volumes:
- .:/application
- /application/node_modules
ports:
- "3000:3000"
depends_on:
- slsdb
コンテナ立ち上げ時にserverless offlineが動く。
ここがポイント
slsappのvolumesに注目。
volumes:
- .:/application
- /application/node_modules
.:/applicationは、"ホストのdocker-compose.ymlと同じ場所のものをコンテナの/applicationにマウントする" 、というよくある感じの記述です。
/application/node_modulesはというと、この記述があることで以下のような挙動をする。
- Dockerfileを元にビルド
- コンテナには
node_modulesが作成される - compose時にカレントディレクトリをマウント
- コンテナ内に存在した
node_modulesを寄せておいて、マウント後に寄せておいたnode_modulesを置き直す
つまり、ビルド時にコンテナ内できるnode_modulesを生かしたまま、ホストのファイル群をマウントできる感じ。
こうすることで、完全にlinux用のnode_modulesが作られる。
もしOS依存のモジュールがあった場合、macで作られたnode_modulesがalpineに入っていて動かないなんてことがあるかもしれない。
それを防げる。
こちらのサイト大変勉強になりました。
https://shotat.hateblo.jp/entry/2016/12/01/221631
補足:ライブリロード
ローカルでファイル編集するたび、tsのコンパイルがされ、ログ出力がされる状態にしたかった。
以下のような感じで設定すれば大丈夫そう。
"noEmitOnError": false
参考までにwebpackの設定も載せておく。
const path = require("path");
const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
module.exports = {
mode: "none",
entry: slsw.lib.entries,
target: "node",
devtool: "source-map",
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader"
}
]
},
resolve: {
extensions: [".ts", ".js", ".tsx", ".jsx"]
},
output: {
libraryTarget: "commonjs",
path: path.join(__dirname, "dist", "lambda"),
filename: "[name].js"
}
};
変更を保存するたびに、エラーがあろうがなかろうがコンパイルしてログ吐くって感じになります。
ただ、WebStormでの挙動がちょっと怪しい雰囲気。
webpackの "Saving in WebStorm" がちょっと気になる。
そのほか自動保存のスパンを1secとかにしてみたりして、調査中。
コンテナ経由でserverlessコマンド
例としてserverless infoを実行するときのコマンドがこんな感じ。
$ docker-compose run --no-deps --rm slsapp npx serverless info
docker runとかで実行しちゃうと、docker-compose.ymlでslsappに環境変数を設定した場合なんかはそれが適用されないので注意。
デプロイ等もこんな感じのコマンドで実行できる。