让我们试着使用Docker创建一个简易的Aidemy(第4部分)〜使用mongodb的数据库〜

简述

这次是Docker简易版Aidemy的第四部分。
之前我们已经创建了前端和后端,所以这次我们将创建数据库。

顺便提一下,之前的链接如下。

用Docker建立一个简易版的Aidemy(第1部分)〜总体结构和Docker的设置〜。链接: https://qiita.com/km42428/items/4e4653aa0e813282986b

让我们用Docker来创建一个简化版本的Aidemy(第2部分)~使用React.js进行前端开发~

让我们通过Docker创建一个简易版的Aidemy(第3部分)~基于Express的后端~

这次的目标

本次目标是创建一个名为mongodb的数据库,并存储练习信息,然后通过后端调用。与以前一样,考虑使用docker-compose来启动。

关于MongoDB

MongoDB是一个开源的数据库,与SQL不同,它将数据以文档形式进行存储。
官方文档可在此处找到:
https://docs.mongodb.com/

顺带一提,文件以JSON或BSON(二进制JSON)的格式保存。

“很多文件的名词有点复杂。”

MongoDB的Docker镜像

MongoDB的官方镜像可在Docker Hub上找到。
https://hub.docker.com/_/mongo/
我们将以这个镜像为基础创建Dockerfile。

更新docker-compose

我们将根据以下内容更新docker-compose.yml文件。


version: "3"
services:
  aidemy-mongodb:
    image: mongo:4.0.3
    ports:
      - "28001:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin-user
      MONGO_INITDB_ROOT_PASSWORD: admin-password
      MONGO_INITDB_DATABASE: admin
    volumes:
      - ./db/:/docker-entrypoint-initdb.d/
  aidemy-frontend:
    build: ./aidemy-frontend
    image: aidemy-frontend
    container_name: aidemy-frontend
    environment:
      - ENV
    ports:
      - 5000:5000
  aidemy-backend:
    build: ./aidemy-backend
    image: aidemy-backend
    container_name: aidemy-backend
    environment:
      - ENV
    ports:
      - 4000:4000
    links:
      - aidemy-mongodb

数据准备

我会将运动信息输入到名为admin的数据库中。

启动aidemy-mongodb容器

$ docker-compose build
$ docker-compose up

进入MongoDB的内部

由于admin数据库需要权限,所以需要使用认证信息登录mongodb。
参考:https://medium.com/@itseranga/enable-mongodb-authentication-with-docker-1b9f7d405a94


$ mongo -u admin-user -p admin-password --authenticationDatabase admin --port 28001
MongoDB shell version v4.0.4
connecting to: mongodb://127.0.0.1:28001/
Implicit session: session { "id" : UUID("1cdc7c13-25c1-4802-9f52-2a71a55f17cf") }
MongoDB server version: 4.0.3
Server has startup warnings:
2018-12-24T08:04:43.407+0000 I STORAGE  [initandlisten]
2018-12-24T08:04:43.407+0000 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2018-12-24T08:04:43.407+0000 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
2018-12-24T08:04:44.050+0000 W CONTROL  [initandlisten]
2018-12-24T08:04:44.050+0000 W CONTROL  [initandlisten]
2018-12-24T08:04:44.050+0000 I CONTROL  [initandlisten]
---
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).

The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.

To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
> 

将练习数据输入

// データベース一覧確認
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

// adminデータベース選択
> use admin
switched to db admin

// exercises コレクション作成
> db.createCollection('exercises')
{ "ok" : 1 }

// exercise コレクションにexercise情報を挿入
> db.exercises.insertMany([
{
  exerciseId: "exercise1",
  title: "1. Hello world",
  script: "# Hello worldを出力しましょう\n",
  answer: "# Hello worldを出力しましょう\nprint('Hello world')"
},
{
  exerciseId: "exercise2",
  title: "2. コメントの入力",
  script: "# 3 + 5 の結果を出力しましょう\n",
  answer: "# 3 + 5 の結果を出力しましょう\nprint(3 + 5)"
}
])
{
        "acknowledged" : true,
        "insertedIds" : [
                ObjectId("5c20943891054e51384ed90d"),
                ObjectId("5c20943891054e51384ed90e")
        ]
}

// 挿入されたか確認
> db.exercises.find()
{ "_id" : ObjectId("5c20943891054e51384ed90d"), "exerciseId" : "exercise1", "title" : "1. Hello world", "script" : "# Hello worldを出力しましょう\n", "answer" : "# Hello worldを出力しましょう\nprint('Hello world')" }
{ "_id" : ObjectId("5c20943891054e51384ed90e"), "exerciseId" : "exercise2", "title" : "2. コメントの入力", "script" : "# 3 + 5 の結果を出力しましょう\n", "answer" : "# 3 + 5 の結果を出力しましょう\nprint(3 + 5)" }
>

如果在插入运动信息时出现错误,可以删除运动集合。

// コレクションの削除
> db.exercises.drop()
true

从aidemy-backend访问MongoDB。

在 aidemy-backend/index.js 中添加以下内容。


app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  res.header(
    "Access-Control-Allow-Methods",
    "GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS"
  );
  next();
});

+ const mongodb = require("mongodb");
+ const MongoClient = mongodb.MongoClient;
+ 
+ // mongodbへの接続文字列
+ var url = "mongodb://admin-user:admin-password@aidemy-mongodb:27017/admin";
+ var exercises;
+ // mongodbの準備ができたらexercisesを初期化する
+ (async function() {
+   console.log("init");
+   for (let i = 0; i < 10; i++) {
+     console.log(i);
+     try {
+       const client = await MongoClient.connect(url);
+       const db = client.db("admin");
+       db.collection("exercises", (err, collection) => {
+         collection.find().toArray((err, docs) => {
+           if (docs.length > 0) {
+             exercises = docs;
+             console.log(docs);
+           }
+         });
+       });
+       break;
+     } catch (err) {
+       console.log(err);
+       await new Promise(resolve => {
+         setTimeout(() => {
+           resolve();
+         }, 1000);
+       });
+       continue;
+     }
+   }
+ })();

- const exercises = [
- {
-   exerciseId: "exercise1",
-   title: "1. Hello world",
-   script: "# Hello worldを出力しましょう\n",
-   answer: "# Hello worldを出力しましょう\nprint('Hello world')"
- },
- {
-   exerciseId: "exercise2",
-   title: "2. コメントの入力",
-   script: "# 3 + 5 の結果を出力しましょう\n",
-   answer: "# 3 + 5 の結果を出力しましょう\nprint(3 + 5)"
- }
- ];

function getExercise(exerciseId) {
  return exercises.find(el => {
    return el.exerciseId === exerciseId;
  });
}

重新启动

$ docker-compose build
$ docker-compose up

这次就到这里了。
下次我们将创建一个执行Python的服务器!