🚚
Dockerで異なるコンテナ間でTypescript型定義ファイルを共有する方法
前書き
クライアントもサーバーもNode.js
に揃えた!もう同じ型定義ファイルを参照して書いていくだけ!
幸せな夢ですよね。しかし、docker
環境での用例が中々見当たらず、試行錯誤を繰り返しました。
本記事で追求したかったもの
以下のポイントを追求しました。
-
docker
ならではのコンテナ間の独立性を維持する - コンテナたちは親子関係ではなく、対等な関係で共有ファイルを参照したい
- プロジェクトのルートは汚さない
- 知らない人が見てわかりやすい(主観)
構造
この記事ではこのような階層を持ったプロジェクトを設定していく例で記事を書きます。
階層が異なる場合は適宜変更してください。
Project Root
┣━ client クライアントのコンテナ
┣━ ...構成ファイル
┗━ tsconfig.json
┣━ server サーバーのコンテナ
┗━ src
┣━ ...構成ファイル
┗━ tsconfig.json
┣━ types 共用で使う型定義ファイルを置くところ
┗━ entities.d.ts
┗━ docker-compose.yml
~~~~~~~~~~~~~~~~~~~~
docker-compose.ymlの設定 (全文)
⚠️ 本記事と関連のない箇所は省略中
services:
client:
volumes: #パス設定の仕方は下記参照
- ./client:/usr/app
- ./types:/usr/types #共通型定義ファイル
# ...その他設定
server:
volumes: #パス設定の仕方は下記参照
- ./server:/usr/src/app
- ./types:/usr/types #共通型定義ファイル
# ...その他設定
以下でそれぞれ説明します。
types
のvolume
設定
後術するtsconfig.json
で、tsconfig.json
からtypes
フォルダまでの経路(相対パス)を書きます。
この経路で両方の環境から参照されるので、一個のパスを使ってホスト(IDE)とコンテナ、どっちからでも辿り着けるように設定しなければいけません。
Volumeの階層をホストの階層に合わせる
ホスト側の階層はいじらずに、コンテナ側の階層関係をホスト側と同じになるように設定します。
やりかたは、ホストでtsconfig.json
=>types
の相対パスを求めたあと、
コンテナ上でtypes
フォルダがどこにあれば、同じ相対パスで参照できるか考えればいいです。
一個一個見て行きましょう。
Client
- ホストでの
tsconfig.json=>types
は../types
- コンテナでの
tsconfig.json
の場所は/usr/app/tsconfig.json
-
/usr/app/tsconfig.jons
から../
移動すると/usr/
になる types
フォルダは/usr/types
にあればいい
ClientのVolume設定
client:
volumes: #パス設定の仕方は下記参照
- ./client:/usr/app
- ./types:/usr/types # <= ここ
Server
- ホストでの
tsconfig.json=>types
:../../types
- コンテナでの
tsconfig.json
の場所は/usr/app/src/tsconfig.json
-
/usr/app/src/tsconfig.json
から../../
移動すると/usr/
になる types
フォルダは/usr/types
にあればいい
ServerのVolume設定
server:
volumes: #パス設定の仕方は下記参照
- ./server:/usr/src/app
- ./types:/usr/types # <= ここ
それぞれのコンテナのtsconfig.json設定
compilerOptions
内のpaths
に登録しておきます。
上で計算したパスを入れていくだけです。
設定を済ませたtsconfig.json
管轄内のtsファイルではimport
ができるようになります。
ファイルを1つ指定して使う場合
{
"compilerOptions": {
"paths": {
"@entities": [ # 好きなように命名
"../types/entities.d.ts"
]
}
}
}
Serverコンテナの例では"../../types/entities.d.ts"
使い方
import { UserEntity } from "@entites" //ファイルを指定しているので、単一ファイルになります。
フォルダを指定して使う場合
{
"compilerOptions": {
"paths": {
"@shared/*": [ # フォルダなので適切な命名
"../types/*.d.ts"
]
}
}
}
Serverコンテナの例では"../../types/*.d.ts"
使い方
import { UserEntity } from "@shared/entities"
おかしいときにみるところ
コンテナのパスがおかしければビルドが失敗します。
ホストのパスがおかしければIDE上でエラーが出る!
Discussion