dockerのマルチステージビルドを使って構築した、vue.jsのアプリがデプロイした際にローカル環境では発生しないエラーが実際のサーバー上でだけ発生する事象が発生しました。
通常通りのやり方だと気づけなかったポイントなので、共有しようと思います。
マルチステージビルドとは?
マルチステージビルドはdockerのimageを作成する際、docker build時にだけ立ち上がるコンテナでそこでできた生成物を実際のイメージに配置するみたいなことができます。
どこかの環境で(jenkins等)node.jsをbuildしてその生成物を配置するみたいな必要がなくなりdockerだけで完結できるようになるのでVue.js の公式も推奨しているデプロイ方法になります。
ハマったポイント
ローカルでnpm install したときに生成される node_modules と サーバーのコンテナ上で生成される node_modules に差分があり、ローカル環境でうまく実行できていたものがサーバーのコンテナ上ではうまく実行されずエラーになってしまった。
原因
ローカル環境で Vue.jsの開発をするときは、npm run dev 等で ローカルのサーバーを立てて開発することが多いと思います。
そのため、 node_modules や dist ファイルは`同じプロジェクト内にローカル環境だけは共存している形になると思います。
ローカルで以下のようなdockerfileをもとにvue.js のプロジェクトをbuildしたのですが、
COPY ./vue ./
RUN npm install
RUN npm run build
このときの COPY の挙動ではローカルに含まれるnode_modules や dist ファイルも一緒にコンテナ内に配置されてしまいます。
そのため、RUN npm install が実行されても、新規でnode_modulesが生成されることがなく baseimageのversionとローカルのversionの差分等があるとうまく生成されないというような事象が発生してしまっていました。
対処方法
.dockerignoreと呼ばれるdockerから無視させるファイルリストを追加する方法があるので、このファイルに以下のように無視ファイルの対象として追加する。
./vue/dist/
./vue/node_modules/
※ディレクトリ階層は使っているものに合わせてください。
追加することで、docker build 時は毎回新規で npm install が走るようになるので、サーバーだろうがローカル環境だろうが同じ状態にすることができ、問題を解決することができました。
さいごに
今回のミスは、たまたまアプリを起動するときに出てくるエラーで動作の一部ができなくなるという感じのエラーではなく気づくことができましたが、ほんとに一部でしか使っていない動作でのエラーとかだとリリースしてからエラーが発生する等の問題になりかねないので注意が必要ですね。
あと、今回差分が発生してしまった一番の大きな原因は dockerの baseimageのversionが node:6.4 とかだったのに対して、ローカル環境が 10くらいになっていたことだったので、プロジェクトの生成からdockerのコンテナ内でやったほうが幸せになれると思いました。 Rubyとかは記事とかそこそこあるんですけどね…