Node.js服務(wù)Docker容器化應(yīng)用實例分析

這篇“Node.js服務(wù)Docker容器化應(yīng)用實例分析”文章的知識點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Node.js服務(wù)Docker容器化應(yīng)用實例分析”文章吧。

創(chuàng)新互聯(lián)公司專注于網(wǎng)站建設(shè)|網(wǎng)站建設(shè)維護(hù)|優(yōu)化|托管以及網(wǎng)絡(luò)推廣,積累了大量的網(wǎng)站設(shè)計與制作經(jīng)驗,為許多企業(yè)提供了網(wǎng)站定制設(shè)計服務(wù),案例作品覆蓋塑料袋等行業(yè)。能根據(jù)企業(yè)所處的行業(yè)與銷售的產(chǎn)品,結(jié)合品牌形象的塑造,量身定制品質(zhì)網(wǎng)站。

docker 化一個 node.js 應(yīng)用程序

在本篇開始我們先創(chuàng)建一個簡單的 node.js 應(yīng)用,然后為這個應(yīng)用創(chuàng)建一個 docker 鏡像,并構(gòu)建和運(yùn)行它

創(chuàng)建 node.js 項目

首先我們需要創(chuàng)建一個 app.js 開啟一個 http 服務(wù),后面會借助 docker 來運(yùn)行這個程序

const http = require('http');
const port = 30010;

const server = http.createserver((req, res) => {
 res.end('hello docker');
})

server.listen(port, () => {
 console.log('running on http://localhost:', port, 'node_env', process.env.node_env);
});

然后我們創(chuàng)建一個 package.json 文件,這里是描述你的應(yīng)用程序以及需要的依賴,寫過 node.js 的同學(xué)應(yīng)該會很熟悉的,這里我在 scripts 里面增加了npm run dev、npm run pro兩個命令,因為我想在這里介紹如何在構(gòu)建時傳入?yún)?shù)來動態(tài)設(shè)置環(huán)境變量。

{ 
 "name": "hello-docker", 
 "version": "1.0.2",
 "description": "", 
 "author": "may",
 "main": "app.js", 
 "scripts": {
 "dev": "node_env=dev node app.js",
 "pro": "node_env=pro node app.js"
 }
}

dockerfile 文件

這是一個 dockerfile 文件所包含的信息,這些命令在docker 入門與實踐中也有講解過

from node:10.0-alpine

run apk --update add tzdata \
 && cp /usr/share/zoneinfo/asia/shanghai /etc/localtime \
 && echo "asia/shanghai" > /etc/timezone \
 && apk del tzdata

run mkdir -p /usr/src/nodejs/

workdir /usr/src/nodejs/

# add npm package
copy package.json /usr/src/nodejs/package.json
run cd /usr/src/nodejs/
run npm i

# copy code
copy . /usr/src/nodejs/

expose 30010

cmd npm run dev

在 dockerfile 的同級文件下創(chuàng)建一個 .dockerignore 文件,避免將你本地的調(diào)試文件、node_modules 等一些文件放入 docker 容器中

.git
node_modules
npm-debug.log

此時通過以下命令即可構(gòu)建一個 docker 鏡像

$ docker image build -t mayjun/hello-docker

再通過 docker run -d -p 30010:30010 mayjun/hello-docker 命令可運(yùn)行一個 docker 容器,但是有個疑問我是有生產(chǎn)和測試之分的,按照上面cmd npm run dev這樣寫死只能打包一種環(huán)境,當(dāng)然你也可以在建一個文件來實現(xiàn)或者一些其它的方法。

動態(tài)設(shè)置環(huán)境變量

為了解決上面的疑問,我的想法是在鏡像構(gòu)建時傳入?yún)?shù)來動態(tài)設(shè)置環(huán)境變量,對 dockerfile 文件做下修改,看以下實現(xiàn):

expose 30010

arg node_env # 新增加
env node_env=$node_env # 新增加
cmd npm run ${node_env} # 修改

下面對上面的代碼做個解釋

  • 通過 arg 指令定義了一個變量,用戶可以在構(gòu)建時通過使用 --build-arg = 標(biāo)志的 docker build 命令將其傳遞給構(gòu)建器 arg node_env

  • 在 dockerfile 中使用 env 引用這個變量 env node_env=$node_env

  • 這一步就是使用了 cmd npm run ${node_env}

剩下的就是在構(gòu)建鏡像時動態(tài)傳入?yún)?shù)了

$ docker image build --build-arg node_env=dev -t mayjun/hello-docker:1.0.2 . # 構(gòu)建測試環(huán)境
$ docker image build --build-arg node_env=pro -t mayjun/hello-docker:1.0.2 . # 構(gòu)建生產(chǎn)環(huán)境

運(yùn)行容器

$ docker run -d -p 30010:30010 mayjun/hello-docker:1.0.2
$ docker ps
container id image   command   created  status  ports   names
2bc6e62cd0e8 mayjun/hello-docker:1.0.2 "/bin/sh -c 'npm run…" 3 minutes ago up 3 minutes 0.0.0.0:30010->30010/tcp elastic_bouman

查看容器日志

docker logs -f 2bc6e62cd0e8

> hello-docker@1.0.0 dev /usr/src/nodejs
> node_env=dev node app.js

running on http://localhost: 30010 node_env dev

我將以上代碼打包成了鏡像 mayjun/hello-docker:1.0.2,可以拉取查看 docker pull mayjun/hello-docker:1.0.2

docker 與 node.js 私有 npm 包

如果你的項目中使用了私有 npm 包,在 dcoker 構(gòu)建鏡像過程中會出現(xiàn) npm 私有包安裝 404 的錯誤,如果是在容器外部我們可以 npm login 登陸擁有 npm 私有包權(quán)限的賬戶,來解決這個問題,但是在 docker 的時候是不能這樣做的。

創(chuàng)建身份驗證令牌

為了安裝私有包我們需要 “創(chuàng)建身份驗證令牌” 以便在持續(xù)集成環(huán)境、docker 容器內(nèi)部能訪問我們的私有 npm 包,如何創(chuàng)建可參考

實現(xiàn)方法

我們在創(chuàng)建 dockerfile 文件過程中就需要增加以下兩條命令:

# 528das62-e03e-4dc2-ba67-********** 這個 token 就為你創(chuàng)建的身份驗證令牌 token
run echo "//registry.npmjs.org/:_authtoken=528das62-e03e-4dc2-ba67-**********" > /root/.npmrc
run cat /root/.npmrc

egg 框架 docker 容器化

在 egg 里面,如果是egg-scripts start --daemon,去掉 --daemon直接 egg-scripts start 即可,否則 docker 容器會無法啟動。

看以下代碼示例,修改下 package.json 即可,dockerfile 文件同上面第一個docker 化一個 node.js 應(yīng)用程序是一樣的

package.json

{
 "scripts": {
 "start": "egg-scripts start" // 去掉 --daemon
 }
}

也可參考 egg issues “docker容器不能run起來,請問有碰到的嗎?”

docker 鏡像體積與構(gòu)建時間優(yōu)化

如果一個鏡像在不經(jīng)過優(yōu)化的情況下體積通常都是會很大的,以下也是在實踐過程中做的幾點(diǎn)優(yōu)化。

run/copy 分層

dockerfile 中的每條指令都會創(chuàng)建一個鏡像層,dockerfile 指令或復(fù)制的項目文件在沒有修改變動的情況下,每個鏡像層是可以被復(fù)用和緩存的。

以下代碼可在 mayjun/hello-docker:latest 鏡像倉庫找到,以下示例中,源碼改變之后,不管 package.json 有沒有改變的情況下都會重新安裝 npm 模塊,這樣顯然是不好的,因此下面我們要改進(jìn)

# ...

workdir /usr/src/nodejs/hello-docker
copy . /usr/src/nodejs/hello-docker

run npm install

# ...

改進(jìn)之后的代碼如下所示,我們讓 package.json 提前,在 package.json 沒有修改的情況下是不會重新安裝 npm 包的,也會減少部署的時間。

# ...

workdir /usr/src/nodejs/

# add npm package
copy package.json /usr/src/app/package.json
run cd /usr/src/app/
run npm i

# copy code
copy . /usr/src/app/

# ...

node.js alpine 鏡像優(yōu)化

mayjun/hello-docker:1.0.0 這個鏡像在 docker 倉庫也可搜索到,在未優(yōu)化之前大約在 688mb

$ docker imagesrepository tag image id created sizemayjun/hello-docker 1.0.0 7217fb3e9daa 5 seconds ago 688mb

使用 alpine 優(yōu)化

alpine 是一個很小的 linux 發(fā)行版,想要大幅度減小鏡像體積選擇 node.js 的 alpine 版本也是最簡單的,另外 -alpine 的時區(qū)默認(rèn)不是國內(nèi)的,需要 dockerfile 配置時區(qū)。

from node:10.0-alpine

run apk --update add tzdata \
 && cp /usr/share/zoneinfo/asia/shanghai /etc/localtime \
 && echo "asia/shanghai" > /etc/timezone \
 && apk del tzdata

run echo "asia/shanghai" > /etc/timezone

run mkdir -p /usr/src/nodejs/

workdir /usr/src/nodejs/

# add npm package
copy package.json /usr/src/app/package.json
run cd /usr/src/app/
run npm i

# copy code
copy . /usr/src/app/

expose 30010
cmd npm start

重新打包了一個版本 mayjun/hello-docker:1.1.0 再次查看下效果,可以看到鏡像文件從 688mb 減少至 85.3mb,這個體積優(yōu)化還是很大的

$ docker images
repository  tag   image id  created  size
mayjun/hello-docker 1.1.0  169e05b8197d 3 minutes ago 85.3mb

生產(chǎn)環(huán)境不要打包 devdependencies 包

有些測試環(huán)境用的包,在進(jìn)行生產(chǎn)環(huán)境打鏡像時不要包含進(jìn)去,也就是 package.json 文件 devdependencies 對象,通過在 npm i 之后指定 --production 參數(shù)過濾

改進(jìn)如下所示:

from node:10.0-alpine

# 省略 ...

# add npm package
copy package.json /usr/src/app/package.json
run cd /usr/src/app/
run npm i --production # 改變在這了

# 省略 ...

重新打包了一個版本 mayjun/hello-docker:1.2.0 再次查看下效果,可以看到鏡像文件從 85.3mb 又減少至 72.3mb

$ docker images
repository  tag   image id  created  size
mayjun/hello-docker 1.2.0  f018aa578711 3 seconds ago 72.3mb

常見問題

question1

以下命令在刪除鏡像的時候報如下錯誤:

$ docker rmi 6b1c2775591e
error response from daemon: conflict: unable to delete 6b1c2775591e (must be forced) - image is referenced in multiple repositories

細(xì)心的你也許會發(fā)現(xiàn)鏡像 id 6b1c2775591e 同時指向了 hello-docker 和 mayjun/hello-docker 倉庫,這也是造成刪除失敗的原因

$ docker images
repository  tag   image id  created  size
MySQL   5.7   383867b75fd2 6 days ago  373mb
hello-docker  latest  6b1c2775591e 7 days ago  675mb
mayjun/hello-docker latest  6b1c2775591e 7 days ago  675mb

指定 repository 和 tag 來刪除,執(zhí)行刪除命令之后再次查看 mayjun/hello-docker 倉庫就已經(jīng)沒有了

$ docker rmi mayjun/hello-docker
$ docker images   
repository  tag   image id  created  size
mysql  5.7   383867b75fd2 6 days ago  373mb
hello-docker latest  6b1c2775591e 7 days ago  675mb

question2

執(zhí)行刪除鏡像命令報如下錯誤:

$ docker rmi 9be467fd1285
error response from daemon: conflict: unable to delete 9be467fd1285 (cannot be forced) - image is being used by running container 1febfb05b850

根據(jù)提示是有正在運(yùn)行的容器,需先停止容器、刪除容器之后在刪除鏡像

$ docker container kill 1febfb05b850 # 停止容器
$ docker rm 1febfb05b850 # 刪除容器
$ docker rmi 9be467fd1285 # 刪除鏡像

question3

設(shè)定的工作目錄(workdir)要與下面的要保持一致

...
workdir /usr/src/nodejs/

# add npm package
copy package.json /usr/src/node/package.json # 目錄不一致
run cd /usr/src/node/ # 目錄不一致
run npm i
...

例如,如以上配置因為工作目錄與實際 copy 的目錄不一致,會導(dǎo)致報以下錯誤:

Node.js服務(wù)Docker容器化應(yīng)用實例分析

再按照以下方式更改為一致即可

...
workdir /usr/src/nodejs/

# add npm package
copy package.json /usr/src/nodejs/package.json # 更改為一致
run cd /usr/src/nodejs/ # 更改為一致
run npm i
...

以上就是關(guān)于“Node.js服務(wù)Docker容器化應(yīng)用實例分析”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

分享題目:Node.js服務(wù)Docker容器化應(yīng)用實例分析
分享URL:http://muchs.cn/article42/ihcchc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)軟件開發(fā)、網(wǎng)站策劃、網(wǎng)站排名、App開發(fā)、網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管