Firebase フロントエンド(Vue.js)/Cloud Functions を同一docker-composeで実行する際に感じたこと
はじめに
2019/12/30現在において、Firebaseを開発する際に生じる不都合の一つとして、node version管理があると思います.
Cloud Functionsの開発において、nodeのバージョンはversion8、あるいは10がサポートされています.
Cloud Functions ランタイムに関数をデプロイするには Firebase CLI が必要です。Node.js バージョン 8 と 10 がサポートされています。Node.js と npm をインストールする場合は、Node Version Manager をおすすめします。
https://firebase.google.com/docs/functions/get-started?hl=ja
つまり、こんなことが頻発します.
[dorakueyon]% yarn build
yarn run v1.19.2
error functions@: The engine "node" is incompatible with this module. Expected version "8". Got "10.15.3"
error Commands cannot run with an incompatible environment.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
このように、異なるversionが依存する開発では、その依存性をDockerに閉じ込めることで幸せになれます.
参考として、githubにcodeを置かせていただきました.
Vue.js + Cloud Functionsのフォルダ構成
Docker化する前に、プロジェクトを作成した上でフォルダ構成をみてみます.
- Vue.js + Firebaseプロジェクト作成
$ vue create project-name
$ firebase init
- フォルダ構成 (node_modules配下を除いています)
.
├── README.md
├── babel.config.js
├── firebase.json
├── functions
│ ├── node_modules
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ └── tsconfig.json
├── node_modules
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── assets
│ ├── components
│ ├── main.ts
│ ├── router
│ ├── shims-tsx.d.ts
│ ├── shims-vue.d.ts
│ └── views
├── tsconfig.json
└── yarn.lock
FrontとCloud Functionsを開発する場合、プロジェクト直下と./funcions直下とで開発環境が分かれます.
それぞれにDockerfileを配置した上で、プロジェクト直下にdocker-compose.ymlを配置します.
- Dockerファイルを追加したフォルダ構成 (node_modules配下を除いています)
.
├── Dockerfile <-
├── README.md
├── babel.config.js
├── docker-compose.yml <-
├── firebase.json
├── functions
│ ├── Dockerfile <-
│ ├── node_modules
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ └── services
│ │ └── project-name -> ../../../src/services/project-name <- シンボリックリンク
│ └── tsconfig.json
├── node_modules
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── assets
│ ├── components
│ ├── main.ts
│ ├── router
│ ├── services
│ │ └── project-name <- シンボリックリンク先
│ │ └── constants.ts
│ ├── shims-tsx.d.ts
│ ├── shims-vue.d.ts
│ └── views
├── tsconfig.json
└── yarn.lock
Docker化
Docker化にむけて、下記の要件があります.
- プロジェクト直下のfirebase関連ファイル(firebase.json, .firebaserc)を、./functions側でも参照したい
- ./functions側からプロジェクト直下の定数やtypeをシンボリックリンクで参照する場合がある
上記を念頭に、Dockerfile/docker-compose.yml
を作成します.
プロジェクト直下のDockerfile
- こちらは特に考えることはありません
FROM node:12-alpine
ENV WORKDIR /work
WORKDIR $WORKDIR
COPY package.json $WORKDIR
RUN yarn
COPY tsconfig.json $WORKDIR
COPY *.config.js $WORKDIR/
COPY public $WORKDIR/
COPY src $WORKDIR/src
EXPOSE 8080
CMD yarn serve
./functionsのDockerfile
./functions/Dockerfileと、./docker-comose.ymlを比較しながらご確認ください.
- WORKDIRを
/work/functions
とする - ./functions直下のファイルCOPYは、コピー元をプロジェクト直下からの相対パスで指定する
- プロジェクト直下のファイルCOPYは、コンテナの
/work
配下に設置する
FROM node:8-alpine
ENV WORKDIR /work/functions
WORKDIR $WORKDIR
COPY ./functions/package.json $WORKDIR
RUN yarn
# firebase
RUN yarn global add firebase-tools
COPY ./functions/tsconfig.json $WORKDIR
COPY ./functions/lib $WORKDIR/lib
COPY ./functions/src $WORKDIR/src
# # for symbolic link (./functions/src/services/project-name)
# COPY ./src/services/project-name /work/src/services/project-name
# firebase
COPY firebase.json /work
COPY .firebaserc /work
# COPY ./functions/.runtimeconfig.json $WORKDIR # if needed
# COPY ./functions/credentials $WORKDIR/credentials # if needed
# settings for runtime emulator
ENV HOST 0.0.0.0
EXPOSE 5000
EXPOSE 9005
プロジェクト直下のdocker-compose.yml
- 上記Cloud FunctionsのDockerfileにあわせるため
build:
のcontext, dockerfileを別に指定する - symbolic linkされている(プロジェクト直下にある)実体ファイルの変更もfunctions側のdockerに反映させるため、
./src:/work/src
を追加
version: '3'
services:
main:
build: .
container_name: front
volumes:
- ./public:/work/public
- ./src:/work/src
ports:
- 8080:8080
tty: true
command: yarn serve
functions:
build:
context: ./
dockerfile: ./functions/Dockerfile
container_name: functions
volumes:
- ./functions/lib:/work/functions/lib
- ./functions/src:/work/functions/src
- ./src:/work/src # for symbolic link
# environment:
# - GOOGLE_APPLICATION_CREDENTIALS=./credentials/firebase-adminsdk.json
ports:
- 5000:5000
- 9005:9005
tty: true
開発の場合
開発環境立ち上げます
$ docker-compose build && docker-compose up
その後の開発は下記のようにすすめます
front
http://localhost:8080
にVue.jsプロジェクトがホットリロードされます
Cloud Functions
こちらは多少面倒ではあります
- dockerコンテナに入る
- firebase loginしていなければfirebase loginを実施
- firebase serveやfirebase functions:shellなどでdebugging
以下 docker exec functions -it sh
してコンテナ内で
$ firebase login # if you are not logged in.
$ firebase serve
$ firebase functions:shell
Cloud Functionsのデバッグについてはまだペインが多いです..
firebase loginの認証情報を永続化(都度fireabase login
したくない)人は下記のサイトが参考になるかもしれません(試していません..)
deploy
- github actions/ circleCIなど利用したほうがよいでしょう.
おわりに
少し強引な形となってしまいましたが、Dockerの恩恵をうけることができる状態までできました.
ただし、./functions/Dockerfile
のフォルダのコンテキストが親階層直下にある点に気持ち悪さがあります.
ここの気持ちわるさの解消は今後の課題とします.