1. 程式人生 > >[Docker] mongodb容器化:初始化資料並掛載到本地

[Docker] mongodb容器化:初始化資料並掛載到本地

去年一門課程,用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