概要
今回は、Dockerで簡易版Aidemyをつくってみようシリーズのその4です。
前回までにフロントエンド・バックエンドを作成したので、今回はデータベースを作成します。
ちなみに、前回までのリンクは以下です。
Dockerで簡易版Aidemyをつくってみよう (その1) ~全体構成とDockerのセットアップ~
https://qiita.com/km42428/items/4e4653aa0e813282986b
Dockerで簡易版Aidemyをつくってみよう (その2) ~React.jsによるフロントエンド~
https://qiita.com/km42428/items/989dac5e7450501c452d
Dockerで簡易版Aidemyをつくってみよう (その3) ~Expressによるバックエンド~
https://qiita.com/km42428/items/f5f7e8f15546b0673d95
今回の目標
今回は mondodb
というデータベースを作成し、エクササイズの情報を格納することと、それをバックエンドから呼び出せるようにすることを目標にします。こちらも、今までと同様に docker-compose
で起動することを考えます。
mongodb について
mongodbとは、オープンソースのデータベースで、SQLとは異なりドキュメントという形式でデータを保存しています。
公式ドキュメントはこちらです。
https://docs.mongodb.com/
ちなみにドキュメントはJSONないしBSON(Binary JSON)という形式で保存されています。
https://www.mongodb.com/json-and-bson
(ドキュメントという言葉がたくさんでてややこしい。。)
mongodb のDocker Image
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
というデータベースにexercise情報を入れていきます。
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()
---
>
exercisesデータを入れる
// データベース一覧確認
> 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)" }
>
※ もし、exercise情報挿入で間違ってしまった場合は、exercisesコレクションを削除する
// コレクションの削除
> 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を実行するサーバを作成します!