Cloud Datastore Emulator を Node.js から Docker コンテナ間で接続利用する

docker-compose を利用して、なるべくミニマムな作りにしようと。。。
するも、まぁまぁ大仰しい感じになってしまった。

## ディレクトリ構成

```
.
├── .env
├── containers
│   ├── gcloud
│   │   ├── Dockerfile
│   │   └── datastore.sh
│   └── node
│       └── Dockerfile
├── docker-compose.yml
└── src
    ├── client
    │   ├── package.json
    │   └── src
    └── server
        ├── package.json
        └── src
```

こんなノリ

## gcloud 用コンテナ

公式のSDKイメージから。最小限で。
エミュレータ起動用shellに実行権限付与。

```
## ./containers/gcloud/Dockerfile

FROM google/cloud-sdk:latest

ADD datastore.sh /datastore.sh
RUN chmod +x /datastore.sh

```

## エミュレータ起動用 shell

gcloudのコンテナ内で、datastoreのエミュレータを立ち上げる起動式。

$DATASTORE_PROJECT_ID は .env から。

オプションなしで起動すると、コンテナ内でしかアクセスできないので、
--host-port=0.0.0.0:8081 として起動。

これで別コンテナ（node)からもアクセスできるようになる。

エミュレータで使う分には、gcloudのprojectのconfigだけセットしてあればいい。
（gcloud auth loginとか特にいらない）

```
## ./containers/gcloud/datastore.sh

#!/bin/sh

gcloud config set project $DATASTORE_PROJECT_ID
gcloud beta emulators datastore start --host-port=0.0.0.0:8081

```

## Node.js 用コンテナ

こちらも公式のイメージから最小限で。


```
## ./containers/node/Dockerfile

FROM node:10

RUN npm -g config set user root

# 必要あればglobalの依存ライブラリインストール
RUN npm i -g typescript
RUN npm i -g @angular/cli@7.3.9
```

## docker-compose.yaml

```
## ./docker-compose.yaml

version: '3'

services:
  gcloud:
    build: ${COMPOSE_PROJECT_ROOT}/containers/gcloud
    tty: true
    environment:
      - DATASTORE_PROJECT_ID=${DATASTORE_PROJECT_ID}
    volumes:
      - ${COMPOSE_PROJECT_ROOT}/src:/src:cached
  node:
    build: ${COMPOSE_PROJECT_ROOT}/containers/node
    tty: true
    working_dir: /src
    volumes:
      - ${COMPOSE_PROJECT_ROOT}/src:/src:cached
    environment:
      - DATASTORE_EMULATOR_HOST=${DATASTORE_EMULATOR_HOST}
      - DATASTORE_PROJECT_ID=${DATASTORE_PROJECT_ID}
    ports:
      - '80:8080' # for web
      - '8082:8000' # for google-cloud-gui
      - '8080:4200' # for angular serve
```

* services:
  * gcloud, node をサービスとして用意。
* **tty:true**
  * どちらもコンテナ内にて作業したいので 
* **${COMPOSE_PROJECT_ROOT}** .envから
  * mac/win 用にプロジェクトルートの相対/絶対パスを指定してる。
* volumes:
  * gcloud側からsrc見たりする必要があるのならマウントしたり。
* node:ports:
  * ホスト機との接続用にexposeする（必要あれば）
* **gcloud:environment:-DATASTORE_PROJECT_ID**
  * エミュレータのプロジェクトID指定用に
* **node:environment:-DATASTORE_EMULATOR_HOST**
* **node:environment:-DATASTORE_PROJECT_ID**
  * エミュレータへの接続用に



## コンテナ用環境変数 .env

```
## ./.env

### Datastore Emulator
DATASTORE_EMULATOR_HOST=gcloud:8081
DATASTORE_PROJECT_ID=ideodora-sandbox001
```

**DATASTORE_EMULATOR_HOST=gcloud:8081**
nodeコンテナ側から見た、エミュレータへの接続用ホスト+ポート

**DATASTORE_PROJECT_ID=ideodora-sandbox001**
任意のgcpプロジェクト名


## コンテナ起動

```
docker-compose up -d
```

楽チン

## エミュレータの起動

```
docker-compose exec gcloud bash
./datastore.sh
```

これで、nodeからは**gcloud:8081**で繋ぎに行ける。

## node側

```
docker-compose exec node bash

npm i @google-cloud/datastore
```

で、あとは環境変数で接続用の値が入ってるので、

```
## ./src/server/index.ts

import { Datastore } from '@google-cloud/datastore';

const datastore = new Datastore();
```

と、特にprojectIdだったりなんなりをDatastoreのオプションに渡すことなく、エミュレータに接続できる。


## おまけ

エミュレータのdatastoreに保存したデータをのぞき見できるライブラリが便利でよく使ってる。
[npm: google-cloud-gui](https://www.npmjs.com/package/google-cloud-gui)

```
docker-compose exec node bash

npm i google-cloud-gui

google-cloud-gui --skip-browser
```

で、起動して、ブラウザから、 http://localhost:8082 にアクセスして
datastoreの保存データをweb上のguiで見れたりできるので便利。