14年畢業(yè)后開(kāi)始接觸node,今天就想跟大家聊聊怎么把nodeclub項(xiàng)目源碼構(gòu)建成一個(gè)鏡像。話說(shuō)Docker是今年剛接觸的,還在入門(mén)中,下面我簡(jiǎn)單介紹下Docker、Dockerfile的語(yǔ)法以及如何把nodeclub源碼構(gòu)建成鏡像。
1.什么是docker?
Docker allows you to package an application with all of its dependencies into a standardized unit for software development.
Docker是一個(gè)開(kāi)源的應(yīng)用容器引擎,讓開(kāi)發(fā)者可以打包他們的應(yīng)用以及依賴包到一個(gè)可移植的容器中,然后發(fā)布到任何流行的 Linux 機(jī)器上,也可以實(shí)現(xiàn)虛擬化。容器是完全使用沙箱機(jī)制,相互之間不會(huì)有任何接口(類似 iPhone 的 app)。幾乎沒(méi)有性能開(kāi)銷,可以很容易地在機(jī)器和數(shù)據(jù)中心中運(yùn)行。重要的是,他們不依賴于任何語(yǔ)言、框架包括系統(tǒng)。
Docker 的目標(biāo)是實(shí)現(xiàn)輕量級(jí)的操作系統(tǒng)虛擬化解決方案。Docker 的基礎(chǔ)是 Linux 容器(LXC)等技術(shù)。在 LXC 的基礎(chǔ)上 Docker 進(jìn)行了進(jìn)一步的封裝,讓用戶不需要去關(guān)心容器的管理,使得操作更為簡(jiǎn)便。用戶操作 Docker 的容器就像操作一個(gè)快速輕量級(jí)的虛擬機(jī)一樣簡(jiǎn)單。
下面的圖片比較了 Docker 和傳統(tǒng)虛擬化方式的不同之處,可見(jiàn)容器是在操作系統(tǒng)層面上實(shí)現(xiàn)虛擬化,直接復(fù)用本地主機(jī)的操作系統(tǒng),而傳統(tǒng)方式則是在硬件層面實(shí)現(xiàn)。

2.Dockerfile簡(jiǎn)單入門(mén)
Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands you would normally execute manually in order to build a Docker image. By calling docker build from your terminal, you can have Docker build your image step by step, executing the instructions successively.
Docker通過(guò)讀取Dockerfile文件中的指令自動(dòng)構(gòu)建鏡像。Dcokerfile是一個(gè)文本文件,它包含了構(gòu)建鏡像所需要執(zhí)行的全部命令。執(zhí)行docker build命令,Docker就會(huì)按照文檔執(zhí)行并終創(chuàng)建一個(gè)鏡像。
Dockerfile支持支持的語(yǔ)法命令如下:
INSTRUCTION argument
指令不區(qū)分大小寫(xiě)。但是,命名約定為全部大寫(xiě)。
Dockerfile都必須以FROM命令開(kāi)始。 FROM命令會(huì)指定鏡像基于哪個(gè)基礎(chǔ)鏡像創(chuàng)建,接下來(lái)的命令也會(huì)基于這個(gè)基礎(chǔ)鏡像(譯者注:CentOS和Ubuntu有些命令可是不一樣的)。FROM命令可以多次使用,表示會(huì)創(chuàng)建多個(gè)鏡像。具體語(yǔ)法如下:
FROM <image name>
例如:
FROM /nodejs
上面的指令告訴我們,新的鏡像將基于的Node.js的鏡像來(lái)構(gòu)建。
繼FROM命令,DockefFile還提供了一些其它的命令以實(shí)現(xiàn)自動(dòng)化。在Dockerfile文件中這些命令的順序就是它們被執(zhí)行的順序。
下面我們就了解下這些有趣的Dockerfile命令吧。
1.MAINTAINER:設(shè)置該鏡像的作者。語(yǔ)法如下:
MAINTAINER <author name>
2.RUN:在shell或者exec的環(huán)境下執(zhí)行的命令。RUN指令會(huì)在新創(chuàng)建的鏡像上添加新的層面,接下來(lái)提交的結(jié)果用在Dockerfile的下一條指令中。語(yǔ)法如下:
RUN <command>
3.ADD:復(fù)制文件指令。它有兩個(gè)參數(shù)<source>和<destination>。destination是容器內(nèi)的路徑。source可以是URL或者是啟動(dòng)配置上下文中的一個(gè)文件。語(yǔ)法如下:
ADD <src> <destination>
4.CMD:提供了容器默認(rèn)的執(zhí)行命令。 Dockerfile只允許使用一次CMD指令。 使用多個(gè)CMD會(huì)抵消之前所有的指令,只有后一個(gè)指令生效。 CMD有三種形式:
CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2
5.EXPOSE:指定容器在運(yùn)行時(shí)監(jiān)聽(tīng)的端口。語(yǔ)法如下:
EXPOSE <port>;
6.ENTRYPOINT:配置給容器一個(gè)可執(zhí)行的命令,這意味著在每次使用鏡像創(chuàng)建容器時(shí)一個(gè)特定的應(yīng)用程序可以被設(shè)置為默認(rèn)程序。同時(shí)也意味著該鏡像每次被調(diào)用時(shí)僅能運(yùn)行指定的應(yīng)用。類似于CMD,Docker只允許一個(gè)ENTRYPOINT,多個(gè)ENTRYPOINT會(huì)抵消之前所有的指令,只執(zhí)行后的ENTRYPOINT指令。語(yǔ)法如下:
ENTRYPOINT ["executable", "param1","param2"]
ENTRYPOINT command param1 param2
7.WORKDIR:指定RUN、CMD與ENTRYPOINT命令的工作目錄。語(yǔ)法如下:
WORKDIR /path/to/workdir
8.ENV:設(shè)置環(huán)境變量。它們使用鍵值對(duì),增加運(yùn)行程序的靈活性。語(yǔ)法如下:
ENV <key> <value>
9.USER:鏡像運(yùn)行時(shí),設(shè)置一個(gè)UID。語(yǔ)法如下:
USER <uid>
10.VOLUME:授權(quán)訪問(wèn)從容器內(nèi)到主機(jī)上的目錄。語(yǔ)法如下:
VOLUME ["/data"]
3.把nodeclub構(gòu)建成一個(gè)鏡像
先把我寫(xiě)的Dockerfile貼出來(lái):
# Dockerfile to create a nodeclub image
FROM /nodejs
MAINTAINER Carrotzpc
# Add files to the image
RUN mkdir -p /opt/nodejs
ADD . /opt/nodejs
WORKDIR /opt/nodejs
# Install the dependencies modules
RUN npm install
# Run make build
RUN make build
# Expose environment variables
ENV MONGO_CARROT_ADDR **LinkMe**
ENV MONGO_CARROT_PORT **LinkMe**
ENV MONGO_CARROT_DATABASE admin
ENV MONGO_CARROT_USER **ChangeMe**
ENV MONGO_CARROT_PASS **ChangeMe**
# Expose the container port
EXPOSE 5000
ENTRYPOINT ["node", "app.js"]
這么簡(jiǎn)單的幾行命令,就可以構(gòu)建出一個(gè)nodeclub鏡像。下面我重點(diǎn)聊一下環(huán)境變量ENV,nodeclub的源碼我用的是node + mongo(無(wú)redis)的版本,mongo配置信息通過(guò)環(huán)境變量傳遞,這就需要我們簡(jiǎn)單修改一下nodeclub的配置文件,我在配置文件中增加了以下代碼(不過(guò)直接在配置文件里邊這樣寫(xiě)不太好),用來(lái)獲取mongo數(shù)據(jù)庫(kù)連接字符串:
// Get mongodb connec string from env
function _getMongoUrl(){
var db_addr = process.env.MONGO_CARROT_ADDR;
var db_port = process.env.MONGO_CARROT_PORT;
var db_user = process.env.MONGO_CARROT_USER;
var db_pass = process.env.MONGO_CARROT_PASS;
var db_database = process.env.MONGO_CARROT_DATABASE;
var db_url = 'mongodb://';
if (db_user && db_pass) {
db_url += (db_user + ':' + db_pass + '@');
}
db_url += (db_addr? db_addr: 'localhost');
db_url += ':' + (db_port? db_port: 27017);
db_url += '/' + (db_database? db_database: 'admin');
console.log('Connect to MongoStore Use this url:' + db_url);
return db_url;
}
到這里我們完成了源碼的修改,其中Dockerfile是放在源代碼根目錄的。現(xiàn)在可以開(kāi)始構(gòu)建nodeclub鏡像了,Windows安裝Docker比較蛋疼,我本地沒(méi)有安裝Docker環(huán)境,我用的是TenxCloud時(shí)速云的本地客戶端tce,安裝配置都比較簡(jiǎn)單,這里就不說(shuō)了,大家可以參考官方文檔。
在命令行中輸入tce login填寫(xiě)用戶名、密碼后完成登錄,然后進(jìn)入到源代碼根目錄,執(zhí)行tce push nodeclub命令,tce會(huì)自動(dòng)將Dockerfile及引用的本地文件打包成zip,并上傳到TenxCloud,由TenxCloud的容器引擎構(gòu)建Docker 鏡像,我們可以看到Docker構(gòu)建鏡像的相關(guān)日志:

完成構(gòu)建后打開(kāi)時(shí)速云網(wǎng)站,進(jìn)入鏡像市場(chǎng)>我的鏡像就可以看到我們剛剛構(gòu)建的鏡像nodeclub:

在鏡像詳情頁(yè)可以上傳鏡像圖標(biāo)、修改鏡像信息、服務(wù)接口等,我們把Dockerfile中的ENV增加到服務(wù)接口中,用于在部署鏡像時(shí)填寫(xiě)mongo的相關(guān)配置信息:

萬(wàn)事具備,只欠一個(gè)mongo了,正好時(shí)速云有提供mongo的鏡像,于是我部署了一個(gè)mongo,然后在部署nodeclub時(shí)填寫(xiě)這個(gè)mongo的地址、端口等信息,這樣就完成了nodeclub的部署:

還有一種方式就是把mongo也集成到我們的鏡像中,這就涉及到了mongo的安裝以及啟動(dòng),我們留在下一次討論。我把源代碼上傳到了github,大家有興趣的話可以自己構(gòu)建試試:https://github.com/Carrotzpc/docker-nodeclub。 示例網(wǎng)站:http://nodeclub-k9nmf.q1.tenxcloud.net:46141/。 PS:由于部署鏡像前host并不可知,所以我把源碼改成了通過(guò)req.headers.host來(lái)獲取host,這樣激活郵件中的鏈接就可用了。(責(zé)編/魏偉)
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個(gè)人觀點(diǎn), 并不代表本站贊同其觀點(diǎn)和對(duì)其真實(shí)性負(fù)責(zé),本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個(gè)個(gè)人學(xué)習(xí)交流的平臺(tái),網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對(duì)作者和來(lái)源進(jìn)行了通告,但是能力有限或疏忽,造成漏登,請(qǐng)及時(shí)聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對(duì)此聲明的最終解釋權(quán)。