This article is the 15th day article of "[Meister Guild] Genuine Advent Calendar 2020".
Not long ago, Windows System for Linux2 (WSL2) was released. You can now run Linux on Windows. Also, by using WSL2, you can use Docker Desktop for Windows even on home Windows. Unexpectedly, some people may not know this. Home I used to use Docker ToolBox, but it wasn't a very good experience and I didn't have much motivation for Docker. However, when I used Docker Desktop for Windows, it was very easy to use, so I tried to build an environment to develop a TS application with Firebase Cloud Functions as the back end with Docker. I will try Vue.js for the front. This is an article summarizing the results.
↓ is a directory structure diagram of files related to environment construction explained in this article. Of course, there are other source files and application configuration files as well.
Directory configuration diagram
.
├──app
│ ├──functions
│ │ ├──lib
│ │ ├──node_modules
│ │ ├──.dockerignore
│ │ ├──copy-node_modules.sh
│ │ ├──Dockerfile
│ │ └──package.json
│ │
│ ├──vuejs
│ │ ├──dist
│ │ ├──node_modules
│ │ ├──.dockerignore
│ │ ├──copy-node_module.sh
│ │ ├──Dockerfile
│ │ └──vue.vonfig.js
│ │
│ └──firebase.json
│
├──swagger
│ └──index.yml
│
└──docker-compose.yml
The Docker container group looks like ↓.
By the way, this time I happened to develop an application that does not use DB. If you use DB, you probably keep this configuration if you use Firebase's Cloud Firestore, but if you need something like MySQL, you'll probably want to add a db
container.
This was the first time for me to develop a TS app, but when I built a development environment with Docker, I encountered the following problems.
--Hot reload does not work when sharing TS build destination with Windows --Building is very slow when sharing node_modules with Windows -If * .d.ts is not on the editor side, you will not receive the benefits of the type during development.
The next Firebase spec also bothered me.
--When you launch the emulator, the API will be prefixed with project name/region name /
Let's take a look at each container.
package.json
"scripts": {
...
"emulators": "tsc-watch --onFirstSuccess \"firebase emulators:start --token ${FIREBASE_TOKEN}\""
...
},
...
"dependencies": {
...
"firebase-admin": "^9.2.0",
"firebase-functions": "^3.6.1",
...
}
...
"devDependencies": {
...
"tsc-watch": "^4.2.9"
...
}
Use the Firebase CLI Cloud Functions Emulators (https://firebase.google.com/docs/functions/local-emulator). Introduce tsc-watch
to enable hot reload development.
$ npm run emulators
Launches an emulator that allows you to develop while hot reloading.
firebase.json
...
"hosting": {
"public": "vuejs/dist",
...
"rewrites": [
{
"source": "/get-users",
"function": "get-users"
}
]
},
"emulators": {
"functions": {
"host": "0.0.0.0",
"port": 5001
},
"hosting": {
"host": "0.0.0.0",
"port": 5000
},
"ui": {
"enabled": true,
"host": "0.0.0.0",
"port": 4000
}
}
...
Firebase settings.
hosting
first specifies the public directory as the default build destination for Vue.js (public
). In rewrites
, each function of Cloud Functions can be called by accessing/~
. This is because the API endpoint provided by Cloud Functions Emulators has the project name and region name in the prefix, but I want to ignore this prefix part when hitting the API from Swagger (project in Swagger's yml file). I don't want to write the name and region name). If the API increases, it will be necessary to add it here.
In emulators
, host
is specified so that it can be accessed from outside Docker, and the UI screen of Cloud Functions Emulators is enabled so that the smallest port number is assigned. You may not use it often, but this will open the dashboard-like screen of the emulator with "OPEN IN BROWSER" of Docker Desktop for Windows.
docker-compose.yml
volumes:
firebase-node_modules:
firebase-lib:
services:
firebase:
build: ./app/functions
image: firebase
container_name: firebase
ports:
- 4000:4000
- 5000:5000
- 5001:5001
volumes:
- ./app:/app
- firebase-lib:/app/functions/lib
- firebase-node_modules:/app/functions/node_modules
environment:
- FIREBASE_PROJECT
- FIREBASE_TOKEN
I don't want to share node_modules with the host, so I create separate volumes and store them there. If the code after transpiling the TS is also shared with the host side, it will prevent hot reloading, so we do the same.
FIREBASE_TOKEN
is for hitting the Firebase CLI without logging in. You can get it at https://firebase.google.com/docs/cli?hl=ja#cli-ci-systems.
Dockerfile
FROM node:10
RUN apt-get update && \
npm install -g firebase-tools
WORKDIR /app/functions
COPY package*.json ./
CMD npm install \
&& firebase use ${FIREBASE_PROJECT} --token ${FIREBASE_TOKEN} \
&& npm run emulators
EXPOSE 4000 5000 5001
firebase-tools
I am doing. I'm copying package * .json
here because the volume mount I wrote in docker-compose.yml
isn't in Docker yet because it's after processing the contents of the Dockerfile.
.dockerignore
node_modules
The host node_modules are not needed, so write them in .dockerignore.
copy-node_modules.sh
#! /bin/bash
SCRIPT_DIR=$(cd $(dirname $0); pwd)
docker cp -a -L firebase:/app/functions/node_modules $SCRIPT_DIR
It is a script that copies the .d.ts
file installed in the Docker container to the host side for development with VS Code on the host. It would be nice to be able to specify the extension with the docker cp
command, but I can't, so I bring node_modules entirely. It takes time. Furthermore, I think that it is related to symbolic links, but it is necessary to execute it with administrator privileges.
Actually, I want to develop by connecting to the Docker container with VS Code's Remote WSL plug-in, but the operation is still unstable in the Preview version, or it freezes frequently in my environment ... I would like to try again when it becomes the official version. If you can use this well, you don't need this script.
After launching the firebase container, you can access the emulator UI from OPEN IN BROWSER.
docker-compose.yml
services:
#Other settings...
swagger:
image: swaggerapi/swagger-ui
container_name: swagger
ports:
- 8000:8080
volumes:
- ./swagger:/var/www
environment:
SWAGGER_JSON: /var/www/index.yml
Make the ./swagger/index.yml file visible on port 8000 on the host side.
After launching the swagger container, you can access the Swagger UI from OPEN IN BROWSER. This container is simple because it simply publishes index.yml.
docker-compose.yml
volumes:
#Other settings...
vuejs-node_modules:
services:
#Other settings...
vuejs:
build: ./app/vuejs
image: vuejs
container_name: vuejs
ports:
- 3000:3000
- 3001:3001
volumes:
- ./app:/app
- vuejs-node_modules:/app/vuejs/node_modules
environment:
- CHOKIDAR_USEPOLLING=true
Make port 3000 for Vue CLI UI and port 3001 for serve.
Again, I don't want to share node_modules with the host, so I'll avoid it with another volume.
The environment variable CHOKIDAR_USEPOLLING
seems to be what you need for a hot reload on serve.
Dofkerfile
FROM node:10
RUN apt-get update && \
npm install -g @vue/cli
WORKDIR /app/vuejs
COPY package*.json ./
CMD npm install \
&& vue ui --host 0.0.0.0 --port 3000
EXPOSE 3000 3001
I have installed the Vue CLI and specified the following in the options of the vue ui
command
---- host 0.0.0.0
Allow access to the WebUI from outside the Docker container
---- port 3000
Launch WebUI on port 3000
.dockerignore
node_modules
Again, the host node_modules is not needed, so write it in .dockerignore.
vue.config.js
module.exports = {
devServer: {
port: 3001,
host: '0.0.0.0'
}
}
Specify the options of the server to be launched by serve in the same way as vue ui
.
copy-node_modules.sh
#! /bin/bash
SCRIPT_DIR=$(cd $(dirname $0); pwd)
docker cp -a -L vuejs:/app/vuejs/node_modules $SCRIPT_DIR
It is a script that copies the .d.ts
file installed in the Docker container to the host side in order to develop with VS Code on the host like the firebase container. It takes time. Execution with administrator privileges is required.
After launching the vuejs container, you can access the Vue CLI UI from OPEN IN BROWSER
.
That's all for building a development environment for Firebase + Vue.js + TS apps using Docker. It seems that the contents here will change depending on the version upgrade of each tool in the future, but as of 2020/12, it was an article that it became like this. Docker is convenient.
Recommended Posts