TiDBローカル環境構築⑥
TiDBのローカル環境の構築を6回目行なっていきます。
前回TiDB環境のDjango構築が出来ましたが、今回はDockerでフロント側の構築を行っていきます。
コンテナ環境のツリー構成
DB構築時のツリー構造は以下のようにしてます。
webフォルダ配下にNestJSの環境を構築していきます。
またルート配下のdocker-compose.ymlでwebコンテナを作成します。
.
├── .env.api
├── .env.web
├── docker-compose.yml
└── src
├── infra
│ └── db
│ ├── Dockerfile
│ ├── data
│ │ └── test_db.sql
│ ├── docker-compose.yml
│ └── entrypoint.sh
└── www
├── api
│ ├── Dockerfile
│ ├── docker-compose.yml
│ ├── entrypoint.sh
│ ├── project
│ │ ├── core
│ │ │ ├── __init__.py
│ │ │ ├── admin.py
│ │ │ ├── apps.py
│ │ │ ├── migrations
│ │ │ │ ├── 0001_initial.py
│ │ │ │ └── __init__.py
│ │ │ ├── models.py
│ │ │ ├── serializers.py
│ │ │ ├── urls.py
│ │ │ └── views.py
│ │ ├── manage.py
│ │ └── project
│ │ ├── __init__.py
│ │ ├── asgi.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ └── requirements.txt
└── web
├── Dockerfile
├── app
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ │ ├── app.controller.ts
│ │ ├── app.module.ts
│ │ └── main.ts
│ ├── tsconfig.build.json
│ └── tsconfig.json
├── docker-compose.yml
└── docker-entrypoint.sh
ソースコードを作成
webコンテナの各ファイルの追加と編集を行います。
ルートのdocker-compose.ymlを編集します。
services:
tiup-playground:
extends:
file: ./src/infra/db/docker-compose.yml
service: tiup-playground
api:
extends:
file: ./src/www/api/docker-compose.yml
service: api
depends_on:
- tiup-playground
# 以下を追加
web:
extends:
file: ./src/www/web/docker-compose.yml
service: web
networks:
tidb-net:
name: tidb-net
driver: bridge
環境ファイルを作成します。
PORT=3000
API_BASE=http://api:8000/api
API_TOKEN=
この Dockerfile は、Node.js 20 の軽量 Alpine イメージをベースに、NestJS CLI をグローバルインストールし、docker-entrypoint.sh をエントリーポイントとして設定して、ポート 3000 でアプリを起動できる環境を構築します。
FROM node:20-alpine
WORKDIR /app
RUN apk add --no-cache libc6-compat
RUN npm install -g @nestjs/cli
COPY docker-entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
EXPOSE 3000
ENTRYPOINT ["sh", "/usr/local/bin/entrypoint.sh"]
このスクリプトは /app に移動後、package.json がなければ NestJS プロジェクトを新規作成し、package-lock.json の有無で npm ci または npm install を実行して依存関係を整え、最後に指定ポートで NestJS を開発モード起動します。
#!/bin/sh
set -e
cd /app
if [ ! -f package.json ]; then
echo "[web] No package.json found. Bootstrapping a new Nest project into /app ..."
nest new app --directory . --skip-git --skip-install --strict --package-manager npm
fi
if [ -f package-lock.json ]; then
npm ci
else
npm install
fi
export PORT="${PORT:-3000}"
echo "[web] Starting Nest in dev mode on port ${PORT} ..."
exec npm run start:dev
この docker-compose サービス定義は、web コンテナを Dockerfile からビルドし、/app を作業ディレクトリに設定、ホストの 3000 番ポートをコンテナの 3000 番にマッピング、.env.web から環境変数を読み込み、api サービス起動後に依存関係を npm ci または npm install で整えて NestJS を開発モードで起動する構成です。
services:
web:
build:
context: .
dockerfile: Dockerfile
working_dir: /app
ports:
- "3000:3000"
env_file:
- ../../../.env.web
depends_on:
- api
volumes:
- ./app:/app
command: >
sh -lc "
if [ -f package-lock.json ]; then npm ci; else npm install; fi
&& npm run start:dev
"
networks:
- tidb-net
これは TypeScript の tsconfig.json 設定で、CommonJS モジュール形式・ES2021 ターゲット・デコレータ有効化・型チェック厳格化などを指定し、ソースを ./dist に出力する構成です。
{
"compilerOptions": {
"module": "CommonJS",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "ES2021",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"strict": true,
"skipLibCheck": true,
"moduleResolution": "node"
}
}
これは NestJS の最小構成プロジェクト用 package.json で、アプリ名や依存関係、ビルド・起動・フォーマット用のスクリプトを定義しています。
{
"name": "nest-hello-app",
"version": "0.1.0",
"private": true,
"description": "Minimal NestJS Hello World (HTML) app for Docker bind mount",
"license": "MIT",
"main": "dist/main.js",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"start": "node dist/main.js",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\""
},
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.0"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
"typescript": "^5.4.0",
"ts-node": "^10.9.2",
"@types/node": "^20.11.0",
"prettier": "^3.2.0",
"rimraf": "^5.0.5"
}
}
NestJS のコントローラで、/ への GET リクエストに対して HTML を返すシンプルなサンプル実装です。
import { Controller, Get, Header } from '@nestjs/common';
@Controller()
export class AppController {
@Get()
@Header('Content-Type', 'text/html; charset=utf-8')
getHello(): string {
return `
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Hello Nest</title></head>
<body>
<h1>Hello World from NestJS!</h1>
<p>This is a sample page served by NestJS inside Docker.</p>
</body>
</html>
`;
}
}
NestJS アプリのルートモジュールで、AppController を登録してアプリ全体の構成を定義しています。
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
@Module({
imports: [],
controllers: [AppController],
providers: [],
})
export class AppModule {}
これは NestJS アプリのエントリーポイントで、AppModule からアプリを生成し、環境変数 PORT またはデフォルトの 3000 番ポートで待ち受けを開始します。
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(process.env.PORT || 3000);
console.log(`Nest app is listening on port ${process.env.PORT || 3000}`);
}
bootstrap();
以下のURLにアクセスするとNestのトップページが確認できました。
まとめ
- TiDB ローカル環境構築シリーズの第6回として、Docker上にNestJSフロント環境を追加した
- webフォルダ配下にNestJSの最小構成を作成し、docker-compose.ymlでapiサービスと連携できるようにした
- DockerfileでNode.js 20 (Alpine) + NestJS CLI 環境を用意し、docker-entrypoint.shで新規プロジェクト生成と依存関係インストールを自動化
- tsconfig.jsonとpackage.jsonを設定し、最小構成の NestJS Hello World HTML ページを作成
- ブラウザで http://127.0.0.1:3000/にアクセスし、NestJSのレスポンスを確認できた
Discussion