We have decided to develop an application using Node.js Express MongoDB as a contract development. I would like to record the knowledge gained during development within a range that does not hinder it. Aside from the contents of the application, since we will develop it as a team, we will first build a development environment using Docker.
--Create an app container and mongodb container using docker-compose. --Save data in the test model using the connection test (mongoose) between the app container and the mongodb container. --Confirm data insertion from mongo compass --Provide authentication for mongodb. The authority of the user to create is "root", "read", "owner" --Database password etc. are managed by environment variables (remove from git management with gitignore)
※important point
If it is
"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 //Empty directory
├── 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=<password>
MONGO_INITDB_DATABASE=<DB name>
.gitignore.
node_modules/
data/
.env
secret_file/
docker-compose.yml
version: '3'
services:
app:
build: ./docker_app
container_name: <app name>_app_cnt
ports:
- "8080:3000"
restart: always
working_dir: /app
tty: true
volumes:
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
- ./src:/app
env_file:
- ./secret_file/db.env
command: bash
networks:
- <app name>-network
depends_on:
- mongo
mongo:
image: mongo:latest
container_name: <app name>_db_cnt
ports:
- "27018:27017"
restart: always
environment:
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.d
env_file:
- ./secret_file/db.env
command:
- mongod
networks:
- <app name>-network
networks:
<app name>-network:
external: true
Dockerfile.
FROM node:12
WORKDIR /app
RUN npm install
db.env
DB_USER=owner
DB_PASS=<password>
DB_NAME=<app name>_db
mongo_init_user.js
let users = [
{
user: "read",
pwd: "<password>",
roles: [
{
role: "read",
db: "<app name>_db"
}
]
},
{
user: "owner",
pwd: "<password>",
roles: [
{
role: "dbOwner",
db: "<app name>_db"
}
]
},
{
user: "readWriteUser",
pwd: "<password>",
roles: [
{
role: "readWrite",
db: "<app name>_db"
}
]
}
];
for (let i = 0, length = users.length; i < length; ++i) {
db.createUser(users[i]);
}
initTestsController.js
"use strict";
const InitTest = require('../models/init_test');
const test = () => {
let initTest = new InitTest({
name: "Taro",
age: 20
})
initTest.save((error, data) => {
if (error) {
console.log(error);
}
console.log(data);
})
}
module.exports = { test };
init.test.js
"use strict";
const mongoose = require("mongoose");
const initTestSchema = new mongoose.Schema({
name: String,
age: Number
});
module.exports = mongoose.model("InitTest", initTestSchema);
package.json
{}
host.
docker-compose build
The following warning appears, but there is no problem.
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.
host.
#Temporarily put the container inside the start container (--Delete after stopping with rm. After starting the container, enter bash)
docker-compose run --rm app /bin/bash
In the app container.
# express-Generate application template with generator
npx express-generator --view=ejs
If it is rejected by aborting immediately for the following, execute again
destination is not empty, continue? [y/N]
aborting
The second time I will wait with a question, so enter with y
destination is not empty, continue? [y/N] y
Various files such as the following are created.
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
Overwrite the following contents in 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"
}
}
Overwrite the following contents in app.js
app.js
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const mongoose = require("mongoose");
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const initTestController = require('./controllers/initTestsController');
const app = express();
mongoose.connect(
`mongodb://${process.env.DB_USER}:${process.env.DB_PASS}@mongo:27017/<app name>_db`,
{ userNewParser: true }
);
mongoose.set("useCreateIndex", true);
// view engine setup
app.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);/*Initial test routing*/
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Package installation
In the app container.
npm install
Exit the container once
In the app container.
#Exit the container (this temporary container will be deleted)
exit
Restart the container
host.
docker-compose up
Click below to check connection http://localhost:8080/
Check if the data is created by clicking below http://localhost:8080/initTest
If the following log is output, it is successful (in the terminal where 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 |【log】--Successful connection--【log】
Open the terminal in a separate tab and enter the db container
docker exec -it <app name>_db_cnt bash
mongo
//Connect to mongodb
show dbs
//Nothing is displayed.(Make sure it is locked by authentication)
use admin
//Connect to admin database
db.auth("root", "<password>")
//If 1 is returned, authentication is successful
db.system.users.find().pretty()
//User confirmation created
It's okay if each authorized person for the database is created as shown below.
{
"_id" : "admin.root",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
{
"_id" : "uniq_db.read",
"roles" : [
{
"role" : "read",
"db" : "<Database name>_db"
}
]
}
{
"_id" : "uniq_db.owner",
"roles" : [
{
"role" : "dbOwner",
"db" : "<Database name>_db"
}
]
}
{
"_id" : "uniq_db.readWriteUser",
"roles" : [
{
"role" : "readWrite",
"db" : "<Database name>_db"
}
]
}
Recommended Posts