用Docker簡化Nodejs開發(fā)1——開發(fā)環(huán)境

開發(fā)Nodejs應用通常要使用多個中間件,開發(fā)人員要把代碼跑起來就要在自己的機器上把中間件安裝一遍,費時費力态蒂,如果同時開發(fā)多個項目就更麻煩了堰汉,經(jīng)常要改來改去辽社。本文以一個Nodejs+MongoDB項目為例,展示Docker的基本使用方法翘鸭,同時提供了編寫對Docker友好代碼的方法滴铅。

項目說明

tms-api-gw是一個API網(wǎng)關(guān)項目,功能是將收到的http請求根據(jù)業(yè)務規(guī)則轉(zhuǎn)發(fā)到對應的服務就乓,每次收到的請求都要記錄日志汉匙,并進行計數(shù),結(jié)果保存到mongodb中生蚁。

希望通過Docker解決如下幾個問題:

  • 簡化mongodb的部署噩翠,方便開發(fā)人員在本地運行應用。
  • 對nodejs應用進行打包邦投,實現(xiàn)整體發(fā)布伤锚,方便運維人員部署。

Docker

首先請按照官網(wǎng)說明安裝Docker尼摹。

參考:https://docs.docker.com/get-started/#install-docker-desktop

使用Docker首先需要了解imagecontainer的概念见芹,簡單說,image是運行環(huán)境的模版蠢涝,container是根據(jù)模版創(chuàng)建的實例玄呛。imageDockerfile進行定義,可以認為Dockerfile是一個批處理命令和二,通過執(zhí)行命令徘铝,在鏡像上安裝包、復制文件惯吕、設(shè)置參數(shù)惕它。有了image就可以通過run命令生成容器,生成的時候可以指定運行時的參數(shù)废登。如果有多個相關(guān)聯(lián)的容器淹魄,可以通過docker-compose進行整體管理。docker-compose根據(jù)編排文件docker-compose.yml描述被管理的容器堡距,通過docker-compose up命令啟動甲锡,docker-compose down命令關(guān)閉兆蕉,這樣就不用對著每個容器單獨執(zhí)行命令。

參考:https://docs.docker.com/reference/

通常我們需要的image都已經(jīng)有基礎(chǔ)版本缤沦,可以在hub.docker.com上查找虎韵。每個鏡像通常都有一堆版本,最重要的區(qū)別在于image是在哪個linux的版本上建的缸废,建議使用alpine包蓝,因為這個版本最小。

下面我們結(jié)合項目需求具體跑一遍Docker企量。

MongoDB

查找基礎(chǔ)鏡像测萎。

docker search mongo

將鏡像拉到本地。

docker pull mongo

生成并運行容器届巩。

docker run --rm --name tms-api-gw-mongo -p 27017:27017 -d mongo:latest

--rm 當容器退出時自動刪除绳泉。

--name tms-api-gw-mongo 指定容器的名字,后面操作容器時用的到姆泻。

-p 27017:27017 將容器內(nèi)部的27017端口映射到主機的27017 端口零酪。

-d 是指定在后臺運行。

進入容器查看數(shù)據(jù)拇勃。

docker exec -it tms-api-gw-mongo /bin/bash

在容器中用exit命令退出容器四苇。

這時在本地就有了個可用的MongoDB實例,數(shù)據(jù)保存在容器中方咆,每次刪除容器月腋,數(shù)據(jù)就會清除,這樣就總能用一個“干凈”的MongoDB進行開發(fā)瓣赂。

如果需要持久保留MongoDB中的數(shù)據(jù)榆骚,可以讓容器將數(shù)據(jù)寫到本地目錄中,執(zhí)行run命令時指定參數(shù)煌集。

docker run --rm --name tms-api-gw-mongo -p 27017:27017 -v $PWD/storage/mongodb:/data/db -d mongo:latest

-v $PWD/db:/data/db 將主機中當前目錄下的db掛載到容器的/data/db妓肢,作為mongo數(shù)據(jù)存儲目錄。

為了管理容器需要用到幾條命令:

docker ps -a #查看全部容器苫纤,不加-a參數(shù)只顯示運行的碉钠。

docker stop container_name # 停止指定的容器

docker rm container_name # 刪除指定的容器

Docker命令參考:https://docs.docker.com/engine/reference/commandline/cli/

Nodejs

先看看Nodejs官網(wǎng)的這篇文章:https://nodejs.org/zh-cn/docs/guides/nodejs-docker-webapp/,下面是以該文章為基礎(chǔ)進行調(diào)整卷拘。

制作docker鏡像喊废。

在項目根目錄新建Dockerfile文件,文件內(nèi)容如下栗弟,和Nodejs官網(wǎng)文章不一致的地方加了注釋污筷。

FROM node:alpine

# 安裝cnpm
RUN npm install cnpm -g 

WORKDIR /usr/src/app

COPY package*.json ./

# 只安裝dependencies的包,不安裝devDependencies的包乍赫;額外安裝包瓣蛀。
RUN cnpm install --production \
  && cnpm install log4js

COPY . .

# 創(chuàng)建放配置文件的目錄
RUN mkdir config

# 設(shè)置應用的環(huán)境變量
ENV TMS_API_GW_ENV='docker'

EXPOSE 3000

CMD [ "node", "./app.js" ]

COPY . .是把本地當前目錄下的內(nèi)容復制到鏡像的工作目錄下/usr/src/app斤寂,但是,node_modules揪惦,config這些內(nèi)容不需要復制,因此要建立.dockerignore文件罗侯,指定不需要復制的內(nèi)容器腋。

.*
node_modules
config
example

創(chuàng)建鏡像,注意不要丟了最后面的點钩杰。

docker build -t tms-api-gw-node .

用docker images可以查看已有鏡像纫塌。

運行容器

docker run --rm --name tms-api-gw-node -p 5678:3000 -v $PWD/config:/usr/src/app/config -d tms-api-gw-node

如果我們同時開發(fā)多個項目,經(jīng)常會發(fā)生端口沖突的問題讲弄,通過-p參數(shù)就可以在啟動容器時指定端口了措左。

同一份代碼需要在多個環(huán)境中運行,包括:開發(fā)避除,測試怎披,生產(chǎn)等,我們通常是采用配置文件讓代碼和運行環(huán)境解耦瓶摆。利用Docker凉逛,可以把代碼和代碼依賴的標準環(huán)境制作成鏡像,在生成容器時再指定和環(huán)境相關(guān)的配置文件群井,這樣Docker鏡像的整體就變成了一個發(fā)布單元状飞,可以極大簡化運維工作。因此书斜,在Dockerfile中我們創(chuàng)建了空的config目錄诬辈,通過參數(shù)-v $PWD/config:/usr/src/app/config指定使用運行環(huán)境本地的配置文件

前面介紹項目基本情況時提到需要在mongodb中存儲api訪問數(shù)據(jù)荐吉,當應用和mongodb都在容器中運行時就產(chǎn)生了一個問題:mongodb的地址是什么焙糟?

在本地開發(fā)環(huán)境我們通常寫個localhost,但是容器中的localhost是容器并不是宿主機样屠,應用無法訪問到mongodb酬荞。為了解決這個問題,在項目中引入了環(huán)境變量瞧哟,看代碼config/gateway.sample.js混巧。

let host, port
if (process.env.TMS_API_GW_ENV === 'docker') {
  host = 'docker.for.mac.host.internal'
  port = 3000
} else {
  host = 'localhost'
  port = 5678
}
module.exports = {
  ...
}

前面Dockerfile中指定了環(huán)境變量ENV TMS_API_GW_ENV='docker',代碼中可以根據(jù)這個環(huán)境變量進行相應的設(shè)置勤揩,在容器中docker.for.mac.host.internal代表了宿主機的地址咧党,否則還是用localhost,指定端口要和DockerfileEXPOSE的端口一致陨亡,這樣不論是否在容器中Nodejs應用都可以訪問到MongoDB傍衡。

如果容器是在后臺運行深员,想查看Nodejs應用輸出的日志,使用如下命令:

docker logs tms-api-gw-node

因為鏡像是以alpine為基礎(chǔ)制作蛙埂,進入容器的命令需要調(diào)整倦畅,將bash改為sh

docker exec -it tms-api-gw-node /bin/sh

至此我們已經(jīng)可以在容器中運行Nodejs應用绣的。

參考:https://github.com/nodejs/docker-node/blob/master/README.md#how-to-use-this-image

參考:一篇關(guān)于Nodejs使用Docker的最佳實踐叠赐,https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md

docker-compose

雖然已經(jīng)可以用容器把Nodejs應用跑起來,但是還是不夠方便屡江,mongodb和nodejs容器要分別啟停芭概,命令還都挺長。能不能更簡單呢惩嘉?可以罢洲,用docker-compose。

參考:https://docs.docker.com/compose/compose-file/

Docker for Mac已經(jīng)包含了Compose了文黎,所以Mac用戶不用單獨安裝Compose了惹苗。

創(chuàng)建docker-compose.yml文件。

version: '3.7'
services:
  app:
    build: ./
    image: tms-api-gw-node:latest
    container_name: tms-api-gw-node
    ports:
      - '5678:3000'
    volumes:
      - ./config:/usr/src/app/config
    depends_on:
      - mongodb

  mongodb:
    image: mongo:latest
    container_name: tms-api-gw-mongo
    ports:
      - '27017:27017'
    logging:
      driver: none

上面這個文件中指定的邏輯和前面通過run命令分別運行容器是完全等效的耸峭。

啟動容器

docker-compose up -d

關(guān)閉容器

docker-compose down

更新鏡像

docker-compose build

反復更新鏡像會導致產(chǎn)生無效的鏡像鸽粉,通過下面的命令刪除這些無用鏡像。

docker images
<none> <none> cb7a87c0359b 22 minutes ago 170MB

docker rmi $(docker images | grep "^<none>" | awk "{print $3}")

提示:實際在本機寫代碼時并不需要將Nodejs應用做成鏡像再運行抓艳,因為這樣每次修改代碼都要重新build触机,既花費時間又產(chǎn)生許多無用鏡像。這里演示Nodejs應用鏡像主要是為了下一步進行發(fā)布做準備玷或。

總結(jié)

雖然Docker整體比較復雜儡首,但是作為開發(fā)人員只需要掌握基本概念和常用命令就可以把Docker跑起來,可以極大簡化本地開發(fā)環(huán)境的管理工作偏友,建議每個開發(fā)人員都嘗試一下蔬胯。

下一篇研究如何利用Docker進行Nodejs應用的部署。

本系列其他文章

用Docker簡化Nodejs開發(fā)2——開發(fā)環(huán)境到測試環(huán)境

用Docker簡化Nodejs開發(fā)3——用webhook實現(xiàn)自動更新

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末位他,一起剝皮案震驚了整個濱河市氛濒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鹅髓,老刑警劉巖舞竿,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異窿冯,居然都是意外死亡骗奖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來执桌,“玉大人鄙皇,你說我怎么就攤上這事⊙稣酰” “怎么了伴逸?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長膘壶。 經(jīng)常有香客問我错蝴,道長,這世上最難降的妖魔是什么香椎? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮禽篱,結(jié)果婚禮上畜伐,老公的妹妹穿的比我還像新娘。我一直安慰自己躺率,他們只是感情好玛界,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著悼吱,像睡著了一般慎框。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上后添,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天笨枯,我揣著相機與錄音,去河邊找鬼遇西。 笑死馅精,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的粱檀。 我是一名探鬼主播洲敢,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼茄蚯!你這毒婦竟也來了压彭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤渗常,失蹤者是張志新(化名)和其女友劉穎壮不,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體皱碘,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡忆畅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片家凯。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡缓醋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绊诲,到底是詐尸還是另有隱情送粱,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布掂之,位于F島的核電站抗俄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏世舰。R本人自食惡果不足惜动雹,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望跟压。 院中可真熱鬧胰蝠,春花似錦、人聲如沸震蒋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽查剖。三九已至钾虐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間笋庄,已是汗流浹背效扫。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留直砂,地道東北人荡短。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像哆键,于是被迫代替她去往敵國和親掘托。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容