[Docker] mongodb容器化:初始化数据并挂载到本地

版权声明: 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

猜你喜欢

转载自blog.csdn.net/Blanchedingding/article/details/84138083
今日推荐