[Docker] mongodb容器化:初始化資料並掛載到本地
阿新 • • 發佈:2019-01-07
去年一門課程,用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