14年畢業後開始接觸node,15年來帝都找了份工做,一直默默的在cnode社區晃悠,灌過幾回水,今天就想發個處女貼,跟你們聊聊怎麼把nodeclub項目源碼構建成一個鏡像。話說Docker是今年剛接觸的,還在入門中/(ㄒoㄒ)/~~,下面我簡單介紹下Docker、Dockerfile的語法以及如何把nodeclub源碼構建成鏡像。(已經對Docker比較熟悉的小夥伴能夠直接跳到第三個)html
Docker allows you to package an application with all of its dependencies into a standardized unit for software development.
Docker是一個開源的應用容器引擎,讓開發者能夠打包他們的應用以及依賴包到一個可移植的容器中,而後發佈到任何流行的 Linux 機器上,也能夠實現虛擬化。容器是徹底使用沙箱機制,相互之間不會有任何接口(相似 iPhone 的 app)。幾乎沒有性能開銷,能夠很容易地在機器和數據中心中運行。最重要的是,他們不依賴於任何語言、框架包括系統。node
Docker 的目標是實現輕量級的操做系統虛擬化解決方案。Docker 的基礎是 Linux 容器(LXC)等技術。在 LXC 的基礎上 Docker 進行了進一步的封裝,讓用戶不須要去關心容器的管理,使得操做更爲簡便。用戶操做 Docker 的容器就像操做一個快速輕量級的虛擬機同樣簡單。git
下面的圖片比較了 Docker 和傳統虛擬化方式的不一樣之處,可見容器是在操做系統層面上實現虛擬化,直接複用本地主機的操做系統,而傳統方式則是在硬件層面實現。
(圖片來自Docker官方網站)github
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經過讀取Dockerfile文件中的指令自動構建鏡像。Dcokerfile是一個文本文件,它包含了構建鏡像所須要執行的所有命令。執行docker build命令,Docker就會按照文檔執行並最終建立一個鏡像。(這段話是翻譯上面那段話的%>_<%)。 Dockerfile支持支持的語法命令以下:redis
INSTRUCTION argument
指令不區分大小寫。可是,命名約定爲所有大寫。
Dockerfile都必須以FROM命令開始。 FROM命令會指定鏡像基於哪一個基礎鏡像建立,接下來的命令也會基於這個基礎鏡像(譯者注:CentOS和Ubuntu有些命令但是不同的)。FROM命令能夠屢次使用,表示會建立多個鏡像。具體語法以下:mongodb
FROM <image name>
例如:docker
FROM google/nodejs
上面的指令告訴咱們,新的鏡像將基於google的Node.js的鏡像來構建。shell
繼FROM命令,DockefFile還提供了一些其它的命令以實現自動化。在Dockerfile文件中這些命令的順序就是它們被執行的順序。 下面咱們就瞭解下這些有趣的Dockerfile命令吧。 1.MAINTAINER:設置該鏡像的做者。語法以下:數據庫
MAINTAINER <author name>
2.RUN:在shell或者exec的環境下執行的命令。RUN指令會在新建立的鏡像上添加新的層面,接下來提交的結果用在Dockerfile的下一條指令中。語法以下:npm
RUN <command>
3.ADD:複製文件指令。它有兩個參數和。destination是容器內的路徑。source能夠是URL或者是啓動配置上下文中的一個文件。語法以下:
ADD <src> <destination>
4.CMD:提供了容器默認的執行命令。 Dockerfile只容許使用一次CMD指令。 使用多個CMD會抵消以前全部的指令,只有最後一個指令生效。 CMD有三種形式:
CMD ["executable","param1","param2"] CMD ["param1","param2"] CMD command param1
5.EXPOSE:指定容器在運行時監聽的端口。語法以下:
EXPOSE <port>;
6.ENTRYPOINT:配置給容器一個可執行的命令,這意味着在每次使用鏡像建立容器時一個特定的應用程序能夠被設置爲默認程序。同時也意味着該鏡像每次被調用時僅能運行指定的應用。相似於CMD,Docker只容許一個ENTRYPOINT,多個ENTRYPOINT會抵消以前全部的指令,只執行最後的ENTRYPOINT指令。語法以下:
ENTRYPOINT ["executable", "param1","param2"] ENTRYPOINT command param1 param2
7.WORKDIR:指定RUN、CMD與ENTRYPOINT命令的工做目錄。語法以下:
WORKDIR /path/to/workdir
8.ENV:設置環境變量。它們使用鍵值對,增長運行程序的靈活性。語法以下:
ENV <key> <value>
9.USER:鏡像運行時,設置一個UID。語法以下:
USER <uid>
10.VOLUME:受權訪問從容器內到主機上的目錄。語法以下:
VOLUME ["/data"]
先把我寫的Dockerfile貼出來:
# Dockerfile to create a nodeclub image FROM google/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"]
這麼簡單的幾行命令,就能夠構建出一個nodeclub鏡像。下面我重點聊一下環境變量ENV,nodeclub的源碼我用的是node + mongo(無redis)的版本,mongo配置信息經過環境變量傳遞,這就須要咱們簡單修改一下nodeclub的配置文件,我在配置文件中增長了如下代碼(不過直接在配置文件裏邊這樣寫不太好),用來獲取mongo數據庫鏈接字符串:
// 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是放在源代碼根目錄的。如今能夠開始構建nodeclub鏡像了,Windows安裝Docker比較蛋疼,我本地沒有安裝Docker環境,我用的是TenxCloud時速雲的本地客戶端tce,安裝配置都比較簡單,這裏就不說了,你們能夠參考官方文檔。 在命令行中輸入tce login填寫用戶名、密碼後完成登陸,而後進入到源代碼根目錄,執行tce push nodeclub命令,tce會自動將Dockerfile及引用的本地文件打包成zip,並上傳到TenxCloud,由TenxCloud的容器引擎構建Docker 鏡像,咱們能夠看到Docker構建鏡像的相關日誌:
完成構建後打開時速雲網站,進入鏡像市場>個人鏡像就能夠看到咱們剛剛構建的鏡像nodeclub:
在鏡像詳情頁能夠上傳鏡像圖標、修改鏡像信息、服務接口等,咱們把Dockerfile中的ENV增長到服務接口中,用於在部署鏡像時填寫mongo的相關配置信息:
萬事具有,只欠一個mongo了,正好時速雲有提供mongo的鏡像,因而我部署了一個mongo,而後在部署nodeclub時填寫這個mongo的地址、端口等信息,這樣就完成了nodeclub的部署:
還有一種方式就是把mongo也集成到咱們的鏡像中,這就涉及到了mongo的安裝以及啓動,咱們留在下一次討論。我把源代碼上傳到了github,你們有興趣的話能夠本身構建試試:
還有一種方式就是把mongo也集成到咱們的鏡像中,這就涉及到了mongo的安裝以及啓動,咱們留在下一次討論。我把源代碼上傳到了github,你們有興趣的話能夠本身構建試試:https://github.com/Carrotzpc/docker-nodeclub。
示例網站:http://nodeclub-k9nmf.q1.tenxcloud.net:46141/。
PS:因爲部署鏡像前host並不可知,因此我把源碼改爲了經過req.headers.host來獲取host,這樣激活郵件中的連接就可用了。