gRPC x TypeScript を Docker で動かしてみた
はじめに
gRPC x TypeScript を Docker コンテナ上で動かしたくなったので、docker compose 使って、試してみました。
中身は、先日書いたやつを流用したので、そっちも参考にしてもらえればと思います。
というか、そっちも読んでもらうこと前提で書いちゃってます。
加えて、そっちはメルカリのブログ読む前提で書いちゃってます。
gRPC x TypeScript のこと知りたい人はメルカリのブログをとりあえず、読んだら良いと思います。
この記事は、gRPC x TypeScript のことは大体わかるけど、サクッとコンテナ化するところ真似したいって人向けなのかなと思います。
コードは、optimisuke/hello-grpc-nodeに置いてます。
フォルダ構成
フォルダ構成はこんな感じにしました。
.
├── Makefile
├── README.md
├── backend
│ ├── config.ts
│ ├── index.ts
│ ├── node_modules
│ ├── package-lock.json
│ ├── package.json
│ └── proto
├── bff
│ ├── config.ts
│ ├── helloClient.ts
│ ├── index.ts
│ ├── node_modules
│ ├── package-lock.json
│ ├── package.json
│ ├── proto
│ └── tsconfig.json
├── docker-compose.yml
├── package-lock.json
└── schema
├── gen
├── helloworld.proto
├── node_modules
├── package-lock.json
└── package.json
proto は、backend と bff と並列に置くことにしました。
修正点
修正点は、少なくて、docker-compose.yml
を作った部分と、bff から backend にアクセスするときの URL を変更したくらい。
docker-compose.yml
docker-compose.yml
は、こんな感じにしました。
version: "3.1"
services:
bff:
image: node:16
volumes:
- ./bff:/repo
working_dir: /repo
tty: true
networks:
- network
ports:
- 9000:9000
backend:
image: node:16
volumes:
- ./backend:/repo
working_dir: /repo
tty: true
networks:
- network
ports:
- 10000:10000
networks:
network:
すごくシンプルです。backend もports
を指定してローカルからでも gRPC クライアントでアクセスできるようにしました。
URL
gRPC クライアントである bff の URL をこんな感じで変えました。
- import { host, port } from "./config";
+ import { host, port } from "./config";
- const serverURL = `localhost:${port}`;
+ const serverURL = `${host}:${port}`;
export const port = 10000;
export const BFFPort = 9000;
+ export const host = 'backend';
Path
あと、細かいですが、proto から自動生成したコードのパスを変更してます。lint でエラーが出たところを修正してます。
Makefile
最後に、.proto
ファイルから、コード生成するときの Makefile をこんな感じにしました。
# Makefile
OUTPUT=gen
WORK_DIR=/repo
NPM_BIN=$(WORK_DIR)/schema/node_modules/.bin
GRPC_TOOL=$(NPM_BIN)/grpc_tools_node_protoc
TYPESCRIPT_PLUGIN=protoc-gen-ts=$(NPM_BIN)/protoc-gen-ts
COMMAND=$(GRPC_TOOL) --plugin=${TYPESCRIPT_PLUGIN} --js_out=import_style=commonjs,binary:$(OUTPUT) --grpc_out=grpc_js:$(OUTPUT) --ts_out=grpc_js:$(OUTPUT) -I . ./*.proto
.PHONY: protogen
test:
echo `$(COMMAND)`
protogen:
docker run --rm -it -v ${PWD}:$(WORK_DIR) -w $(WORK_DIR)/schema node:16 \
/bin/bash -c "\
npm install \
&& rm -rf $(OUTPUT) \
&& mkdir -p $(OUTPUT) \
&& $(COMMAND) \
&& rm -rf ../bff/proto \
&& cp -r $(OUTPUT) ../bff/proto \
&& rm -rf ../backend/proto \
&& cp -r $(OUTPUT) ../backend/proto\
"
backend と bff の Node のバージョンとそろえたほうが無難かなと思って、こっちもコンテナでやることにしました。
今回、自動生成したコードはシンプルに backend と bff のフォルダにコピーすることにしたので、最後やたらごちゃごちゃした感じになっちゃってます。本番で使うには、管理方法を検討する必要ありそうです。
おわりに
やったことはフォルダ構成考えて、docker-compose.yml
書くくらいで、シンプルでしたが、地味に時間かかりました。
一つのpackage.json
で管理してたものを分割する時、package.json
が置かれてるフォルダの外にある自動生成したコードを参照しようとして、直接的じゃないエラーが出たり、Makefile のエラーがよくわからず、なかなか動かなかったり。
やったらできそうなことは、なかなか手を動かすのサボりがちですが、やってみてよかったかなーと思いました。
Discussion