使用Express和MongoDB在docker-compose上构建GraphQL服务器

总结

    • GraphQLの構築を学んだので、復習として記事にしてみた

 

    • この記事では手順のみを記載し、詳細は説明しない

 

    • この記事のゴールとしてはローカル上でGraphiQLを起動し、そこでクエリを実行しデータを取得するところ

 

    https://github.com/MrFuku/express-graphql-server

生態圈

    • Mac OS Mojave

 

    • docker-compose 1.25.4

 

    • Node.js 14.2

 

    • express 4.17.1

 

    • graphql 15.0.0

 

    MongoDB 4.2.6

创建并切换到项目工作目录。

使用mkdir命令来创建目录,并使用cd命令进行移动。

$ mkdir express-graphql-server
$ cd express-graphql-server

创建docker-compose.yml文件,启动mongoDB。

version: '3'
services:
  mongo:
    image: mongo
    restart: always
    ports:
      - 27017:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
    volumes:
      - ./db/db:/data/db
      - ./db/configdb:/data/configdb

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    depends_on:
      - mongo
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: example
# http://localhost:8081 で Mongo Express が起動
$ docker-compose up
スクリーンショット 2020-05-17 16.44.59.png

【3】打开Express

创建一个名为server的目录,并创建server/Dockerfile文件。

FROM node:14.2-alpine3.11

WORKDIR /server

RUN apk update

COPY . .

# 後にコメントを外す
# COPY package.json ./
# COPY yarn.lock ./

# RUN yarn install

将server容器添加到docker-compose.yml文件中。

version: '3'
services:
  # serverコンテナを追加
  server:
    build: ./server
    tty: true
    ports:
      - 4000:4000
    volumes:
      - ./server/:/server
      - /server/node_modules
    depends_on:
      - mongo

  mongo:
    image: mongo
    restart: always
    ports:
...

启动服务器容器并在容器内安装所需的软件包。

# serverコンテナを立ち上げ、shellを起動する
docker-compose run server sh

# yarnで今回必要となるpackage一式をインストールします
yarn add express express-graphql graphql mongoose nodemon

# コンテナから抜ける
exit

将服务器/Dockerfile按以下方式修改,并在docker-compose.yml中添加命令。

FROM node:14.2-alpine3.11

WORKDIR /server

RUN apk update

# コメントアウト
# COPY . .

# コメントを外す
COPY package.json ./
COPY yarn.lock ./

RUN yarn install
version: '3'
services:
  server:
    build: ./server
    tty: true
    ports:
      - 4000:4000
    volumes:
      - ./server/:/server
      - /server/node_modules
    depends_on:
      - mongo
    command: yarn nodemon app # <- express起動用のcommandを追加

  mongo:
    image: mongo
    restart: always
    ports:
...

创建一个名为server/app.js的文件,并重新构建Docker容器映像。
再次启动容器,验证Express是否成功启动。

const express = require('express')
const app = express()

app.get('/', (req, res) => res.send('Hello World!'))

app.listen(4000, () => console.log('Example app listening on port 4000!'))
# http://localhost:4000 を開いて「Hello World!」と表示される
docker-compose build
docker-compose up

【4】mongoDBにテスト用データベースの作成

スクリーンショット_2020-05-17_18_03_38.png
スクリーンショット_2020-05-17_18_27_26.png
スクリーンショット_2020-05-17_18_05_02.png

然后,我们创建一个用于操作test数据库的用户。
请记下用户名和密码,稍后会用到。

# 起動中のmongoコンテナ内に入り、shellを起動
docker-compose exec mongo sh

# root権限でmongoシェルを起動
mongo -u root -p example

# createUserコマンドでtestデータベースを読み書きできるユーザーを作成
db.createUser({ user: "user", pwd: "password", roles: [{ role: "readWrite", db: "test" }]})

# mongoシェルから抜ける
exit

# mongoコンテナから抜ける
exit

【5】与mongoDB的连接

server/app.jsを次のように書き換え、サーバー起動時にコンソール上に「connected mongoDB」と表示されれば接続成功です

const express = require('express')
const app = express()
+ const mongoose = require('mongoose')
+
+ const user = 'user'
+ const pass = 'password'
+ mongoose.connect(`mongodb://${user}:${pass}@mongo/test`)
+ mongoose.connection.once('open', () => {
+   console.log('connected mongoDB')
+ })
app.get('/', (req, res) => res.send('Hello World!'))

app.listen(4000, () => console.log('Example app listening on port 4000!'))
app_js_—_express-graphql-server.png

【6】GraphQL架构的定义

创建server/models/book.js文件,并定义book模型。

const mongoose = require('mongoose')
const Schema = mongoose.Schema

// nameというフィールドを持つbookモデルを定義
const bookSchema = new Schema({
  name: String,
})

module.exports = mongoose.model('Book', bookSchema)

创建server/schema/schema.js文件,并定义架构。

const graphql = require('graphql')
const Book = require('../models/book')
const { GraphQLSchema, GraphQLObjectType, GraphQLID, GraphQLString } = graphql

const BookType = new GraphQLObjectType({
  name: 'Book',
  fields: () => ({
    id: { type: GraphQLID },
    name: { type: GraphQLString },
  }),
})

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    // idを引数に対象レコードを返すbookクエリを定義
    book: {
      type: BookType,
      args: { id: { type: GraphQLID } },
      resolve(_, args) {
        return Book.findById(args.id)
      },
    },
  },
})

module.exports = new GraphQLSchema({
  query: RootQuery,
})

当在 server/app.js 中添加了 GraphQL 终点的定义,那么就完成了!

const express = require('express')
const mongoose = require('mongoose')
+ const graphqlHTTP = require('express-graphql')
+ const schema = require('./schema/schema')
const app = express()

const user = 'user'
const pass = 'password'
mongoose.connect(`mongodb://${user}:${pass}@mongo/test`)
mongoose.connection.once('open', () => {
  console.log('connected mongoDB')
})
app.get('/', (req, res) => res.send('Hello World!'))
+ app.use('/graphql', graphqlHTTP({
+     schema,
+     graphiql: true,
+   })
+ )

app.listen(4000, () => console.log('Example app listening on port 4000!'))

当你访问 http://localhost:4000/graphql 时,应该会启动GraphiQL。

スクリーンショット 2020-05-17 18.17.59.png

请查询书籍,如果刚刚添加的数据返回了,那就好了!(辛苦了)

スクリーンショット 2020-05-17 18.26.29.png

不久的将来,我计划撰写一篇使用GraphQL创建看板应用程序的文章。

广告
将在 10 秒后关闭
bannerAds