Netlify FunctionsをDockerで実行する

以前、Netlify Functions をローカル環境でエミュレートする方法、Netlify にデプロイする方法をご紹介しました。今回は、ローカル環境で開発した Netlify Fucntions をコンテナ技術の理解を深めるために Docker で実行してみます。前回作成したアプリケーションをもとに話を進めますので、まだの方はそちらを一読されてから読み進めることをオススメします。

Node.js のアプリケーションを Docker のコンテナで実行する

Docker Hub に公開されているnode - Docker Hubのイメージを利用して、Docker コンテナ上で Netlify Functions を実行します。また、作成したアプリケーションを実行するだけでなく、アプリケーションを開発する環境も整えてみます。

Dockerfile

空のイメージ(スクラッチ)を使用して一から環境を構築しても良かったのですが、Node.js の公式テンプレートが Docker Hub に公開されているため、今回はそちらを使用します。Dockerfileを作成しましょう。

# Docker HubのNode.js 8.15のイメージを取得
FROM node:carbon
# COPY、RUNの作業ディレクトリを作成して移動
WORKDIR /app
# NODE_ENV環境変数を指定
ENV NODE_ENV=production
# カレントディレクトリのpackage.jsonとyarn.lockファイルを作業ディレクトリにコピー
COPY package.json yarn.lock ./
# 必要パッケージのインストール
RUN yarn install --frozen-lockfile --no-cache --production
# 現在のディレクトリのファイルを作業ディレクトリにコピー
COPY . .
# Netlify Functionsのビルド
RUN yarn build:server
# 9000番ポートを使用
EXPOSE 9000
# Netlify Functionsを起動
CMD [ "yarn", "start:server" ]

Dockerfileの各行にコメントを補記していますので、そちらも参照してください。簡単な流れを説明すると以下の通りとなります。前回ご紹介した記事を、コンテナ内で実行しているだけであることがお分かりいただけたでしょうか。

  1. yarnで必要なパッケージのみインストール
  2. yarn build:servernetlify-lambda buildを実行
  3. yarn start:serverで 9000 番ポートを使用してリッスン

.dockerignore

上記のDockerfileのままビルドしても良いのですが、このままではCOPY命令実行時にカレントディレクトリの不要ファイルがすべてコピーされてしまいます。COPYファイルから除外したいファイルがある場合は、Dockerfileと同一階層に.dockerignoreファイルを作成します。記述方法は.gitignoreと同様です。

.dockerignore
.DS_Store
.git
Dockerfile
node_modules
npm-debug.log
README.md
/dist
/publish

コンテナのビルド、起動

これで準備は整いました。実際にコンテナのイメージを作成し、コンテナを起動します。今回はビルドしたイメージにnetlify-functionsというタグを付与しました。-tはタグを付与するオプションです。

docker build -t netlify-functions .
docker run -d -p 9000:9000 netlify-functions

コンテナが起動したかどうかは、docker psで確認できます。もし、コンテナの起動に失敗している場合は、docker logs <conainer id>でエラーの原因を追えます。<container id>は、docker run実行時の標準出力で確認できます。

起動に失敗する原因のほとんどは、package.jsonの不備によるインストールパッケージの過不足です。package.jsonの記述内容を見直した上で、再度docker buildコマンドを実行してみましょう。

無事起動できた場合はブラウザを開いて以下の URL にアクセスしてみましょう。Hello, World!と画面上に表示されましたか?

http://localhost:9000/.netlify/functions/hello

Docker 環境で Netlify Functions を開発する

さて、ここまでは既製のアプリケーションを Docker で実行する方法を見てきました。ここからは手法を変えて、Docker 上で Node.js のアプリケーションを開発する方法をご紹介します。ただ、netlify-lambdanvmなどローカルホスト上で Netlify Functions を簡単にエミュレートする方法があるため、あえて Docker コンテナ上で開発するメリットはあまりありません。

docker runコマンドのオプションに-vがあります。これは、ローカルホストのボリュームをコンテナにマウントします。ローカルホストで編集したファイルの変更をコンテナに簡単に反映できます。たとえば、docker runコマンド実行時に、以下のように実行します。

docker run --rm -it -p 9000:9000 -v $(pwd):/app netlify-functions /bin/bash

--rmオプションは、コンテナ停止時に自動的にコンテナを削除するためのオプションです。-itは、コンテナ内でインタラクティブなシェル(今回は、/bin/bash)を実行するためのオプションです。

そして、重要なオプションが-vです。上記ではホスト OS のカレントディレクトリを、コンテナの/appディレクトリにマウントしています。ホスト OS(つまり、Mac)のカレントディレクトリで変更した内容は、すぐにコンテナの/appディレクトリに反映されます。

yarn global add nodemon
nodemon src/lambda/*.js

さて、上記のコマンドを実行するとコンテナ上で対話型シェルを実行できる状態になります。Node.js にはソースコードの変更を検知し、変更があれば自動的にリロードしてくれる便利なnodemonというモジュールがあります。コンテナ内でソースコードの変更を監視し、ホスト OS 上でのアプリケーションの修正をすぐにコンテナに反映させることができます。

以上で、ローカルホスト上に Node.js の実行環境を一切持たずに(Docker の実行環境は必要)、開発環境を整えることができました。

Volume オプションについて

docker run実行時に指定した-vオプションは非常に強力ですが、使い方には注意が必要です。-vオプションは、ホスト OS 上で実行するプロセス(コンテナ)が、自由にホスト OS のファイルを読み書きできることを意味します。今回は、開発環境を整える目的で使用しましたが、商用環境等での使用は控えてなるべくCOPY命令等を使用するべきでしょう。COPY命令は一方通行です。

まとめ

いかがでしたでしょうか。Docker で実行しようと思ったきっかけは、毎回yarn start:serverするのが面倒で常時プロセスとして起動しておきたかったからです。別にコンテナは必須要件ではなくバックグラウンドで起動しておくという手もあったのですが、Docker を久しく持て余していたということもあり、Dockerfileから作成してみました。ぜひ Docker で遊んでみてくださいね。

comments powered by Disqus