Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8957

【アプリ開発 1】【Node.js express Docker】 Dockerを用いてNode.js Express MongoDB(mongoose)の環境を構築する【2020年12月】

$
0
0

※当方駆け出しエンジニアのため、間違っていることも多々あると思いますので、ご了承ください。また、間違いに気付いた方はご一報いただけると幸いです。

Node.js Express MongoDBを用いたアプリ開発

受託開発でNode.js Express MongoDBを用いたアプリ開発を行うことになりました。
開発の中で得られた知見を、支障のない範囲で記録していきたいと思います。
アプリの内容はさておき、チームで開発するため、まずはDockerを用いて開発環境を構築を行います。

構築する環境

  • docker-composeを用いて、アプリコンテナ、mongodbコンテナを作成する。
  • アプリコンテナとmongodbコンテナの接続テスト(mongoose)を用いて、テストモデルにデータ保存。
  • mongo compassからデータの挿入を確認
  • mongodbに認証を設ける。作成するユーザーの権限は"root","read","owner"
  • データベースのパスワード等は環境変数で管理(gitignoreにてgitの管理から外す。)

※注意点
<アプリ名> <パスワード>となっているところは、各自で適当なものを記入してください。
そのまま記載するとエラーとなります。
今回は、パスワードは全て共通としています。

初期インストールするパッケージ一覧

 "bcrypt"
 "body-parser"
 "connect-flash"
 "cookie-parser"
 "debug"
 "ejs"
 "express"
 "express-ejs-layouts"
 "express-generator"
 "express-session"
 "express-validator"
 "http-errors"
 "http-status-codes"
 "method-override"
 "mongoose"
 "morgan"
 "nodemon"
 "passport"
 "passport-local-mongoose"

下準備

最初に用意するファイル群

.
├── .env
├── .gitignore
├── data
│   └── db  //空ディレクトリ
├── docker-compose.yml
├── docker_app
│   └── Dockerfile
├── secret_file
│   ├── db.env
│   └── db_init
│         └──mongo_init_user.js
└── src
    ├── controllers
    │     └── initTestsController.js
    ├── models
    │     └── init_test.js
    └── package.json

env.
MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=<パスワード>
MONGO_INITDB_DATABASE=<DB名>
gitignore.
node_modules/
data/
.env
secret_file/
docker-compose.yml
version:'3'services:app:build:./docker_appcontainer_name:<アプリ名>_app_cntports:-"8080:3000"restart:alwaysworking_dir:/apptty:truevolumes:-/etc/passwd:/etc/passwd:ro-/etc/group:/etc/group:ro-./src:/appenv_file:-./secret_file/db.envcommand:bashnetworks:-<アプリ名>-networkdepends_on:-mongomongo:image:mongo:latestcontainer_name:<アプリ名>_db_cntports:-"27018:27017"restart:alwaysenvironment:MONGO_INITDB_ROOT_USERNAME:${MONGO_INITDB_ROOT_USERNAME}MONGO_INITDB_ROOT_PASSWORD:${MONGO_INITDB_ROOT_PASSWORD}MONGO_INITDB_DATABASE:${MONGO_INITDB_DATABASE}volumes:-./data/db:/data/db-./secret_file/db_init/:/docker-entrypoint-initdb.denv_file:-./secret_file/db.envcommand:-mongodnetworks:-<アプリ名>-networknetworks:<アプリ名>-network:external:true
Dockerfile.
FROM node:12
WORKDIR /app
RUN npm install
db.env
DB_USER=owner
DB_PASS=<パスワード>
DB_NAME=<アプリ名>_db
mongo_init_user.js
letusers=[{user:"read",pwd:"<パスワード>",roles:[{role:"read",db:"<アプリ名>_db"}]},{user:"owner",pwd:"<パスワード>",roles:[{role:"dbOwner",db:"<アプリ名>_db"}]},{user:"readWriteUser",pwd:"<パスワード>",roles:[{role:"readWrite",db:"<アプリ名>_db"}]}];for(leti=0,length=users.length;i<length;++i){db.createUser(users[i]);}
initTestsController.js
"use strict";constInitTest=require('../models/init_test');consttest=()=>{letinitTest=newInitTest({name:"Taro",age:20})initTest.save((error,data)=>{if(error){console.log(error);}console.log(data);})}module.exports={test};
init.test.js
"use strict";constmongoose=require("mongoose");constinitTestSchema=newmongoose.Schema({name:String,age:Number});module.exports=mongoose.model("InitTest",initTestSchema);
package.json
{}

環境作成

コンテナ作成

ホスト.
docker-compose build

下記の様な警告がでるが問題ない。

npm WARN saveError ENOENT: no such file or directory, open '/app/package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open '/app/package.json'
npm WARN app No description
npm WARN app No repository field.
npm WARN app No README data
npm WARN app No license field.
ホスト.
#コンテナを一時的に起動コンテナ内に入る(--rmで停止後削除する。コンテナ起動後、bashに入る)
docker-compose run --rm app /bin/bash
appコンテナ内.
# express-generatorでアプリケーションのひな形を生成
npx express-generator --view=ejs

下記の用に即abortingで拒絶されたら再度実行

destination is not empty, continue? [y/N]
aborting

二回目は質問で待ってくれるので y でエンター

destination is not empty, continue? [y/N] y

下記の様な各種ファイルが作成される。

   create : public/
   create : public/javascripts/
   create : public/images/
   create : public/stylesheets/
   create : public/stylesheets/style.css
   create : routes/
   create : routes/index.js
   create : routes/users.js
   create : views/
   create : views/error.ejs
   create : views/index.ejs
   create : app.js
   create : package.json
   create : bin/
   create : bin/www

package.jsonに下記の内容を上書き

package.json
{"name":"uniq_app","version":"0.0.0","private":true,"scripts":{"start":"nodemon ./bin/www"},"dependencies":{"bcrypt":"^5.0.0","body-parser":"^1.19.0","connect-flash":"^0.1.1","cookie-parser":"~1.4.4","debug":"~2.6.9","ejs":"^3.1.5","express":"~4.16.1","express-ejs-layouts":"^2.5.0","express-generator":"^4.16.1","express-session":"^1.17.1","express-validator":"^6.7.0","http-errors":"~1.6.3","http-status-codes":"^2.1.4","method-override":"^3.0.0","mongoose":"^5.11.9","morgan":"~1.9.1","nodemon":"^2.0.6","passport":"^0.4.1","passport-local-mongoose":"^6.0.1"}}

app.jsに下記の内容を上書き

app.js
constcreateError=require('http-errors');constexpress=require('express');constpath=require('path');constcookieParser=require('cookie-parser');constlogger=require('morgan');constmongoose=require("mongoose");constindexRouter=require('./routes/index');constusersRouter=require('./routes/users');constinitTestController=require('./controllers/initTestsController');constapp=express();mongoose.connect(`mongodb://${process.env.DB_USER}:${process.env.DB_PASS}@mongo:27017/<アプリ名>_db`,{userNewParser:true});mongoose.set("useCreateIndex",true);// view engine setupapp.set('views',path.join(__dirname,'views'));app.set('view engine','ejs');app.use(logger('dev'));app.use(express.json());app.use(express.urlencoded({extended:false}));app.use(cookieParser());app.use(express.static(path.join(__dirname,'public')));app.get('/initTest',initTestController.test);/* 初期テストルーティング */app.use('/',indexRouter);app.use('/users',usersRouter);// catch 404 and forward to error handlerapp.use(function(req,res,next){next(createError(404));});// error handlerapp.use(function(err,req,res,next){// set locals, only providing error in developmentres.locals.message=err.message;res.locals.error=req.app.get('env')==='development'?err:{};// render the error pageres.status(err.status||500);res.render('error');});module.exports=app;

パッケージのインストール

appコンテナ内.
npm install

一度コンテナを抜ける

appコンテナ内.
#コンテナを抜ける(この仮コンテナは削除される)
exit

コンテナを再起動

ホスト.
docker-compose up

下記クリックで接続確認
http://localhost:8080/

mongooseとの接続確認

下記クリックでデータが作成されるか確認
http://localhost:8080/initTest

下記の様なログが出力されれば成功(docker-compose upしたターミナルで)

uniq_app_cnt |   _id: 5fec5a6213a2fd002d89acca,
uniq_app_cnt |   name: 'initTestUser',
uniq_app_cnt |   age: 20,
uniq_app_cnt |   __v: 0
uniq_app_cnt | }
uniq_app_cnt | 【ログ】--接続成功--【ログ】

mongodbの権限周り確認

ターミナルを別タブで開き、dbコンテナに入る

docker exec -it <アプリ名>_db_cnt bash
mongo
//mongodbに接続

show dbs
//何も表示されない。(認証でロックされていることを確認)

use admin
//adminデータベースへ接続

db.auth("root", "<パスワード>")

//1 と返れば認証成功

db.system.users.find().pretty()
//作成されたユーザー確認

以下の様な、データベースに対する各権限者が作成されていたらオッケー。

{"_id":"admin.root","roles":[{"role":"root","db":"admin"}]}{"_id":"uniq_db.read","roles":[{"role":"read","db":"<データベース名>_db"}]}{"_id":"uniq_db.owner","roles":[{"role":"dbOwner","db":"<データベース名>_db"}]}{"_id":"uniq_db.readWriteUser","roles":[{"role":"readWrite","db":"<データベース名>_db"}]}

mongo compassからの接続確認。

image.png


Viewing all articles
Browse latest Browse all 8957