Docker 是一個可以將應(yīng)用容器化的工具露氮,可以簡單的把容器理解為一個和羽毛一樣輕的虛擬機止后,和傳統(tǒng)的虛擬機不同,它并不會給系統(tǒng)帶來太大的負擔盐股,并且有更高的可移植性和擴展性。在容器中應(yīng)用將享有獨立的文件系統(tǒng)耻卡,容器內(nèi)的操作將不會影響到自身的主機系統(tǒng)疯汁,有點類似于三體中的小宇宙空間,在里面可以有高度的自由操作空間卵酪,并且已經(jīng)預(yù)設(shè)了你喜歡的裝修風(fēng)格(應(yīng)用運行所需的環(huán)境)幌蚊!
我們將使用 Docker 來搭建一個最簡單的 Node 容器化應(yīng)用,這個鏡像將會被我們打包溃卡,上傳到自己的 Docker 倉庫溢豆,并且可以開箱即用。想象這么一個場景瘸羡,你的開發(fā)機器將這個應(yīng)用進行容器化以后漩仙,在自己的服務(wù)器上將這個容器化的鏡像下載后,使用一個命令就可以使你的應(yīng)用在另一個完全不同的環(huán)境運行起來最铁,節(jié)約下來的這些時間可以讓我們做更多自己喜歡的事情讯赏,而不是鉆研一個我們可能搞不定的 “Linux 環(huán)境問題”!
第一步:下載并安裝 Docker
下載地址冷尉,希望這一步?jīng)]有難倒你漱挎。
第二步:編寫一個簡單的 Node 應(yīng)用
為了保持足夠簡單,我使用了 Express
雀哨,它只有一個功能磕谅,在主頁輸出一個 Hello Docker
私爷,如果你對此有疑惑,可以參考 源碼倉庫膊夹,也可以參考下面的代碼:
const express = require('express');
const app = express();
app.get("/", (req, res) => {
res.end("Hello Docker!")
});
app.listen(8000, () => {
console.log("server is starting in http://localhost:8000");
});
保險起見衬浑,我們最好使用 node app.js
測試一下這個應(yīng)用是健康的,啟動后瀏覽器打開 http://localhost:8000
放刨,我們可以順利看到 Hello Docker! 被輸出在屏幕上工秩,看來一切在朝著我們期望的方向發(fā)展著。
第三步:將 Node 應(yīng)用裝箱打包成鏡像
這一步可能會接觸到你的知識盲區(qū)了进统,所以我們用一個比較簡單輕松的風(fēng)格來剖析每一步需要做的事情助币,將復(fù)雜的事情分解成多個簡單的步驟,這是我們解決復(fù)雜問題的一貫方式螟碎。
我們在應(yīng)用的同級目錄下新建一個 Dockerfile
文件眉菱,讓這個記錄員幫我們記錄我們接下來要做的事情。你的目錄應(yīng)該看起來跟我的基本一致:
我們的應(yīng)用需要什么掉分?
我們第一個需要思考的問題是俭缓,我們的應(yīng)用需要什么,我們可能知道酥郭,它需要一臺計算機來運行华坦,這個倒是不用擔心,Docker 也需要計算機不从,它能有的我們都可以有季春。那我們的應(yīng)用還需要什么呢,眾所周知消返,Docker 是用 Go 語言實現(xiàn)的,那他會有 Node 的運行環(huán)境嗎耘拇?
不撵颊,它沒有,所以我們第一步是構(gòu)建一個支持 Node 應(yīng)用運行的環(huán)境惫叛,那我們就需要先在這個容器中放進去一個 Node倡勇,怎么放進去呢,一個簡單的命令就可以了嘉涌,在 Dockerfile
中新增一行:
# 這句命令的作用是讓我們的鏡像在 node:10.16-alpine 鏡像的基礎(chǔ)上開始
# alpine 的包會比較小一點妻熊,功能也會少一點,但是已經(jīng)可以滿足我們的需求了
# 站在巨人的肩膀上
FROM node:10.16-alpine
我們需要在容器里做什么仑最?
我們的記錄員 Dockerfile
已經(jīng)幫我們記錄了第一步要做的事情扔役,我們可以在第一步的基礎(chǔ)上思考第二步要做的事情了。
在前面我們提到過警医,在容器中有一個自己的小宇宙亿胸,這個小宇宙雖然我們不常來坯钦,但是我們也應(yīng)該希望它能夠和大宇宙一樣井井有條,所以呢侈玄,我們要在這個容器單獨的文件系統(tǒng)中指定一個工作目錄婉刀,以便我們將來能夠在容器中盡快找到我們的應(yīng)用,所以讓我們的記錄員加上一句:
# 這句命令的作用是指定應(yīng)用在容器中的工作目錄
# 為我們的應(yīng)用找到了一個干凈的房間序仙,它將在這里開始它的一生
WORKDIR /usr/src/app
指定了工作目錄之后突颊,我們希望把我們的應(yīng)用在里面運行,這一步我們需要把我們的核心 app.js
挪到我們在 docker 中的工作目錄中潘悼,一般來說我們會將整個應(yīng)用放進去律秃,所以我們需要加上一句命令:
COPY . .
這樣就可以了嗎?如果你熟悉 Node
項目的話挥等,你就會知道把所有文件都挪進去是不太明智的友绝,至少要把 node_modules
留下,我們不需要親自將這個“龐大笨重的機器”艱難的挪進去肝劲,我們只需要放進去“芯片(app.js
)”和“使用說明(package.json
)”就可以了迁客,然后讓我們的 docker 容器完成對依賴的安裝。
所以我們在當前目錄下新建一個 .dockerignore
文件辞槐,填入 node_modules
掷漱,就像 .gitignore
那樣!
既然我們已經(jīng)把應(yīng)用放進了容器榄檬,那么我們只需要像運行一個普通 Node
項目那樣運行我們的項目就可以了卜范,回憶一下,我們怎么運行我們的 Node
項目呢鹿榜?第一步安裝依賴海雪,第二步 Run it!
那我們需要在 package.json
中的 script
選項中加入一行 "start": "node app.js"
,為我們的項目指定一個啟動入口舱殿。然后我們就可以讓記錄員記錄最后的兩句命令了:
# 安裝依賴
RUN npm install
# 定義應(yīng)用的啟動指令
CMD [ "npm", "start" ]
最終的完整版應(yīng)該是這樣的:
FROM node:10.16-alpine
WORKDIR /usr/src/app
COPY . .
RUN npm install
CMD [ "npm", "start" ]
怎么將我們的應(yīng)用打包成 Docker 鏡像奥裸?
進入你的項目目錄,運行一行命令
# 根據(jù) Dockerfile 配置文件信息將應(yīng)用打包成鏡像
# 執(zhí)行記錄員記錄的所有命令
docker image build -t myapp:1.0 .
在打包完成后沪袭,我們用 docker image ls
命令來看看這孩子長啥樣
它只有 79.6M湾宙,相對于一個 VM 系統(tǒng)來說,它輕的像一根羽毛冈绊,而且還可以更邢丽!
運行你的 Docker 容器死宣!
實踐是檢驗真理的唯一標準伟恶,我們來測試一下我們的容器,它能跑嗎十电?
(如果你想要模擬在另一臺電腦上運行知押,此刻你可以重啟電腦了叹螟,重啟后你得到的將會是一臺全新的電腦!)
我們現(xiàn)在使用一行命令來運行我們的容器:
docker container run --publish 8888:8000 --detach --name app myapp:1.0
在打開瀏覽器之前台盯,我們先剖析一下上面的這行命令:
- docker container run: 運行一個 docker 容器
- --publish: 將主機上的 8888 端口所接收的網(wǎng)絡(luò)流量轉(zhuǎn)發(fā)到容器內(nèi)部的 8000 端口處理罢绽;(我們?nèi)萜鲀?nèi)的 8000 端口上運行著我們的應(yīng)用)
- --detach: 在后臺運行這個容器;
- --name: 為你的容器指定一個名稱静盅,以便你區(qū)分不同的容器良价;
解析完成后,我們此刻應(yīng)該信心百倍蒿叠,打開瀏覽器明垢,輸入 http://localhost:8888
,我們成功了市咽!