【086】部署nodejs程式時,如何把自己用到的npm模組封裝成Docker映象,方便在離線的時候使用?
使用場景
在本文開頭,說一下碰到的使用場景。編寫好nodejs程式後,就要封裝成Docker映象。在編譯Dockerfile的時候,系統會從npm的模組倉庫中下載用到的模組。這會碰到兩個問題:
第一,大多數情況下,我們更新程式,只是改了原始碼,沒有修改package.json中的模組配置。每次編譯映象的時候都要從網路上下載模組浪費時間。
第二,生產環境與外網隔離;或者網路環境不穩定。
我圍繞著這兩個問題給出瞭解決方法,並在本文裡寫出了一個例子。
解決方法
首先我們要建立一個nodejs-base映象,用來儲存我們需要用到的npm模組放到這個docker映象裡面。
建立一個node-js專案,因為這個專案主要為了下載npm模組,所以沒什麼程式,結構簡單,如下所示:
nodejs-base
│
├─Dockerfile
├─main.js
└─package.json
Dockerfile
FROM node:8-onbuild
# set timezone as china/shanghai
RUN cp /usr/share/zoneinfo/PRC /etc/localtime
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
#COPY package.json /usr/src/app/
# copy app source
COPY . /usr/src/app
RUN npm install
CMD ["node","/usr/src/app/main.js"]
main.js
console.log("main")
package.json 把所有專案中用到的模組都寫到這個檔案裡面。為了避免模組自動更新導致出現錯誤,使用了確定版本的寫法。
{
"name": "train-outline",
"version": "0.0.1",
"description": "Learn node.js and express.",
"main": "main.js",
"author": "Zhang Chao" ,
"license": "MIT",
"dependencies": {
"body-parser": "1.17.2",
"cookie-parser": "1.4.3",
"express": "4.15.3",
"jade": "1.11.0",
"multer": "1.3.0",
"superagent": "3.5.2"
}
}
本地編譯執行正常後,把整個node-base資料夾(node_modules除外)上傳到 linux 伺服器上,通過cd命令進入linux裡面的node-base資料夾,輸入如下命令編譯映象:
docker build -t zhangchao/nodejs-base:v1 .
然後我寫一個應用的例子來試一下。
nodejs-base
│
├─.npmrc
├─Dockerfile
├─package.json
├─server.js
├─test.jade
└─yarn.lock
.npmrc
sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
phantomjs_cdnurl=https://npm.taobao.org/mirrors/phantomjs/
electron_mirror=https://npm.taobao.org/mirrors/electron/
registry=https://registry.npm.taobao.org
Dockerfile
FROM zhangchao/nodejs-base:v1
WORKDIR /usr/src/app
# copy app source
COPY . /usr/src/app
EXPOSE 18091
CMD ["node","/usr/src/app/server.js"]
package.json
{
"name": "train-outline",
"version": "0.0.1",
"description": "Learn node.js and express.",
"main": "main.js",
"author": "Zhang Chao",
"license": "MIT",
"dependencies": {
"body-parser": "1.17.2",
"cookie-parser": "1.4.3",
"express": "4.15.3",
"jade": "1.11.0",
"multer": "1.3.0",
"superagent": "3.5.2"
}
}
server.js
// var express = require('express');
// var http = require('http');
// var app = express();
// app.set('view engine', 'jade'); // 設定模板引擎
// app.set('views', __dirname); // 設定模板相對路徑(相對當前目錄)
// app.get('/', function(req, res) {
// res.render('test'); // 呼叫當前路徑下的 test.jade 模板
// })
// var server = http.createServer(app);
// server.listen(3002);
//----------------------------------
var super_request = require('superagent');
var express = require('express');
var app = express();
app.set('view engine', 'jade'); // 設定模板引擎
app.set('views', __dirname); // 設定模板相對路徑(相對當前目錄)
app.use(express.static('public'));// 靜態檔案
// begin
app.get('/', function (req, res) {
var md = "";
md = "Hello world !!!"
res.render('test',{
s:'hello world!',
md:md
});
})
var server = app.listen(18091, function () {
var host = server.address().address
var port = server.address().port
console.log("應用例項,訪問地址為 http://%s:%s", host, port)
})
test.jade
doctype html
html
head
meta(charset="utf-8")
meta(http-equiv="X-UA-Compatible", content="IE=edge")
meta(name="viewport", content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0")
title #{s}
body
div #{md}
編寫好了之後,專案除去node_modules資料夾,上傳到Linux伺服器,用cd命令進入專案資料夾,執行下面的命令:
docker build -t zhangchao/app:v1 .
docker run --name app -p 18091:18091 --restart=always -d zhangchao/app:v1
這樣,當只改原始碼不改package.json時候,只要重新編譯 app 這個映象就可以了。只有在需要更新package.json的時候才需要重新編譯 nodejs-base映象。
如果生產環境要求和外網隔離,先找一臺能連線外網的機器編譯 nodejs-base 映象,然後安裝到生產環境即可。
這種部署方式比較適合需要經常更新的產品或者專案。