先週までDockerなんもわからん状態の私でしたが、お手本コードがあれば何とか起動できるレベルに浮上しました!
今日はExpressで作ったアプリをDockerで起動する手順についてまとめます。
Dockerを使うといいことがある
コマンドひとつでサーバーとDBを起動できる
これまで、ターミナルでmySQLを起動し、次はサーバーを起動する…といった手順を順番に行っていました。
しかし、Dockerを使うと docker compose up だけで両方を一度に起動できます!
環境の同期が簡単
これは複数人で開発する時はもちろん、デプロイ時に威力を発揮します。
例えば、LaravelをXserverにデプロイする時は、開発環境と本番環境を手作業で同期する必要があります。
それに対し、GCPのようにDockerを利用できる環境では、開発環境そのままを本番環境に移行することができます。
Dockerってすごく便利!
ファイルの構成

Dockerfile、docker-compose.ymlをプロジェクトのルートディレクトリに配置します。
Dokerfile
Dockerfileとは、Dockerイメージを作るための指示書です!ここにイメージ作成に必要なコマンドを記述します。
Dockerイメージとは、アプリケーションを実行するための設計図です!このイメージをもとにコンテナ(実行環境)を起動します。
これが今回のアプリのサーバーのDockerfileです。

特徴はステージが2つあるところです。
開発時は必須なファイル、node_modules。とっても容量が大きいファイルなのに実行環境では不要なんです。
不要なファイルは省いて、軽量なコンテナを作りたい!
そんなわががままを、マルチステージビルドがかなえてくれます。
上半分のステージでは、プロジェクト内のコードでビルドを行い、実行環境に必要なファイルを生成しています。
下半分のステージでは、生成したファイルから実行環境に必要なファイルのみを取り出すことで、イメージを軽量化しています。
FROM node:18.16.0 as builder
Docker Hub から公式の Node.js イメージをひっぱってきています。as builder というのは、Builder Stage で用いられる構文です。
WORKDIR /build
コンテナ内での作業ディレクトリの名前を /build に指定します。
npm clean-install と npm run build はこのディレクトリを基準に実行されます。
COPY . /build
ローカルのルートディレクトリを、コンテナ内の作業ディレクトリに移します。
FROM node:18.16.0-slim
Runtime Stage ではnode:18.16.0-slim と指定することで、実行環境用の軽量なイメージを使用しています。
作業ディレクトリを /app に指定し、ここに実行に必要なファイルをCOPYしていきます。
ここで私がはまったポイントが、ejsファイルの入ったviewフォルダです!
react のビルドの場合は、ページを構成するファイルもぎゅぎゅっとバンドルされてdistフォルダに入るのですが、ejs の場合はそうではありません。
ビルド後もviewフォルダに残り、しかもnode_modules/ejsがないと実行時に動きません。
そこで、/build/views/ と /build/node_modules/ejs を /app にCOPYします。
CMD ["node", "dist/index.js"]
コンテナを起動する時に実行されるコマンドを指定しています。ここでは、以下のコマンドと同じ意味になります。
node dist/index.jsこれで、Dockerfileの完成です!
ここまでくれば、docker build でイメージを作成し、docker run でコンテナを実行できます。
あとはmySQLの方のイメージも作り、ネットワークを作成し、サーバーとmySQLをつないで・・・とステップを踏むのですが、これらを一度にすませる魔法の呪文があります!
そう、docker compose up です。
docker-compose.yml
docker-compose.yml とは docker compose コマンドの設定ファイルで、プロジェクトのルートディレクトリに配置します。
このファイル内で、コンテナごとに使用イメージ、ファイル、環境変数などを定義しています。

services とは起動したいコンテナ達のことであり、今回はdb(mySQLのコンテナ)、wait-db、api(サーバーのコンテナ)の3つです。
wait-db は、mySQLのコンテナが起動するまで、サーバーのコンテナを待機させています。
これによって、サーバーが起動したのにmySQLがまだ起動していないので接続できない!といったエラーを回避できます。
mySQLのコンテナは Docker hub の既存のイメージを使用しています。
それに対し、サーバーのコンテナは Dockerfile でカスタマイズたイメージをビルドし使用しています。
mySQL と サーバーの environment(環境変数)をリンクさせることで、これらのコンテナを接続しています。
サーバーのコンテナの環境変数を、app.js の環境変数に使用します。
準備完了
これでdocker compose up で起動できるようになりました。おつかれさまです!
Githubにコードを載せています。
Contribute to risu043/list-app-docker de...
GitHub - risu043/list-app-docker...
github.com
