版权声明: https://blog.csdn.net/Blanchedingding/article/details/84138083
去年一门课程,用nodejs+mongodb重构了一个jsp+servlet+mysql的web网站(具体参见这篇论文),但是网站是本地部署的,数据库也是本地先创建好的,想要把这个网站用docker-compose跑起来,需要写一些脚本、Dockerfile文件和对应的docker-compose文件。
(重点在于数据库的容器化,参考文章:docker-compose 构建mongodb并导入基础数据示例)
- 文件目录结构:
|- project
|- Dockerfile
|- ... (nodejs项目的其它所有目录和文件)
|- mongo
|- data
|- xxx.json (用于初始化的数据库文件)
|- Mongo-Dockerfile
|- setup.sh
|- data
|- db (宿主机挂载目录)
|- docker-compose.yaml
- 本地数据库导出:
mongoexport -d <dbname> -c <collectionname> -o <output json file path> --type json
- 源代码数据库连接部分的修改:
var mongoose = require('mongoose'),
DB_URL = 'mongodb://<mongoService>/<dbName>';
mongoose.Promise = global.Promise;
var reconnectTimeout = 5000; // ms.
/**
* 连接
*/
// mongoose.connect(DB_URL, { useMongoClient: true, autoReconnect: true});
function connect() {
// Catch the warning, no further treatment is required
// because the Connection events are already doing this
// for us.
mongoose.connect(DB_URL, { useMongoClient: true, autoReconnect: true }).catch(function(){
});
}
/**
* 连接成功
*/
mongoose.connection.on('connected', function () {
console.log('Mongoose connection open to ' + DB_URL);
});
/**
* 连接异常
*/
mongoose.connection.on('error',function (err) {
console.log('Mongoose connection error: ' + err);
mongoose.disconnect();
});
/**
* 连接断开
*/
mongoose.connection.on('disconnected', function () {
console.log('Mongoose connection disconnected');
setTimeout(function(){
connect();
}, reconnectTimeout);
});
connect();
module.exports = mongoose;
以为只要改DB_URL,但是发现docker-compose中的depends_on并不能保证mongo先启动好,service第一次尝试连接数据库会失败(挂载到宿主机、第一次初始化的时间还是需要一些时间的),然后就一直不连了。
尝试了mongoose在connect时加上option: autoReconnect:true,然而在第一次连接失败情况下它并不会重新连接!!!很坑好吧。最后按照stackoverflow上的帖子解答,改了源码,在连接报错的时候显式关闭连接,已经关闭连接的时候隔5秒重新建立连接。
- Mongo-Dockerfile文件:
FROM mongo
ENV WORKSPACE /usr/local/work
ENV AUTO_RUN_DIR /docker-entrypoint-initdb.d
ENV INSTALL_MONGO_SHELL setup.sh
RUN mkdir -p $WORKSPACE
COPY ./data/*.json $WORKSPACE/
COPY ./$INSTALL_MONGO_SHELL $AUTO_RUN_DIR/
RUN chmod a+x $AUTO_RUN_DIR/$INSTALL_MONGO_SHELL
- setup.sh文件:
#!/bin/bash
mongo <<EOF
use <dbName>;
db.createCollection("<collectionName>");
EOF
mongoimport --db <dbName> --collection <collectionName> --file $WORKSPACE/<collectionName>.json
这里有一个坑,之前也踩过,但就是不长记性:) 在windows下编辑的.sh文件编码格式为dos,换行符为\r\n,放到centos7里面跑,需要修改编码格式为unix(换行符为\n):
vi setup.sh
:set ff? #可以看到当前文件格式
:set ff=unix #设置成unix格式
:set ff=dos #设置成dos格式
:wq #退出
- 项目的Dockerfile:
FROM node
MAINTAINER dingding
RUN mkdir -p /app
WORKDIR /app
# 我就很简单粗暴(主要是菜),在本地npm install把所有依赖包都下好,打镜像的时候就直接copy进去
# 反正就是把项目所有需要的目录和文件都add进去~~
ADD ./app.js /app/
ADD ./package.json /app/
ADD ./bin /app/bin
ADD ./node_modules /app/node_modules
ADD ./public /app/public
ADD ./routes /app/routes
ADD ./views /app/views
CMD [ "npm", "start" ]
EXPOSE 3000
- docker-compose.yaml文件:
version: '3'
services:
petalk-mongo:
build:
context: petalk-mongo
dockerfile: Mongo-Dockerfile
image: petalk-mongo
ports:
- 27017:27017
volumes:
# 宿主机目录:容器挂载目录
# ./是相对docker-compose文件的路径,/是容器内部的绝对路径
- "./data/db:/data/db"
- "/etc/localtime:/etc/localtime"
networks:
- my-network
petalk-service:
build: petalk-service
image: petalk-service
restart: always
ports:
- 3000:3000
depends_on:
- petalk-mongo
networks:
- my-network
networks:
my-network:
driver: bridge
项目代码:https://github.com/Blanchedingding/ModernWeb/tree/master/Petalk-docker
改进版本(build镜像时下载npm依赖):https://github.com/Blanchedingding/Petalk-docker