Node.js服務端開發教程 (二):新的軟體交付方式

  • 2019 年 11 月 6 日
  • 筆記

在上文中,我們從零開始安裝了必需的一些NestJS開發環境,並使用命令行工具生成了第一個NestJS服務端程式,而且也初步了解了怎麼把這個程式運行起來。

不過,作為一名優秀的軟體工程師,光清楚開發程式的功能,是不太夠的。因為軟體早晚要拿到正式的環境、或其他各種各樣的環境下去運行的,可怕的是,你根本不知道這些環境是什麼作業系統,上面裝了哪些軟體,軟體的版本是什麼!有可能在你開發的電腦上運行的好好的程式,一到其他的電腦上就各種報錯,根本運行不起來或是出現各種奇怪的問題。

這就是程式設計師界著名的「我本地是好的呀」問題。

為了解決這種環境差異帶來的問題,業內陸續出現了各種各樣的解決方案,比如早前的虛擬機,以及最近幾年比較火的容器化。我們今天就想通過容器化的方式,將我們的第一個NestJS程式打包成一個擁有環境一致、程式碼一致、入口單一、不受外界影響的可交付產品。

說到容器化,有些朋友可能會脫口而出:Docker!對,沒錯,我們今天就是要使用到Docker。不過容器化工具不止Docker一種,像CoreOS之類的也是同類產品,只是Docker太出名了,導致很多朋友都把Docker當做容器化的代名詞。另外容器化擴展出來的東西很龐大,比如容器編排(大家肯定聽說過現在大名鼎鼎的Kubernetes,簡稱K8S;還有Docker自家旗下的Swarm),這些容器編排工具在集群管理和微服務領域有著非常重要的作用。內容太多,我們今天只粗淺的了解最簡單的Docker使用。

安裝Docker

沒安裝過Docker的朋友,先來安裝下工具吧。如果你用的是Windows或Mac的電腦,可以從 https://www.docker.com/products/docker-desktop 這個網址下載Docker Desktop;Linux的用戶可以通過各自的包管理工具(yum、apt等)進行安裝。

安裝完成後在命令行上輸入下面的命令,確保Docker服務已經運行起來並正常可用:

docker ps

如果你看到了以下的資訊(只要有紅色的那幾個表頭就行),說明一切已經準備就緒:

如果你看到的是類似如下的資訊,說明你的Docker伺服器程式還沒運行起來,請檢查你的Docker Desktop(Windows、Mac)或dockerd(Linux)是不是正常啟動了:

構建NestJS程式

還記得前文中,我們是怎麼把程式運行起來?

npm run start  # 使用 yarn 則是:yarn run start

這個命令其實執行了2個步驟:

  • 將TypeScript編寫的程式構建轉換成JavaScript程式,放到dist目錄下
  • 通過Node.js執行dist目錄下的main.js主程式

而對於我們發布程式的過程來說,只需要構建就可以了,並不需要運行。因此,我們只需要執行項目的構建命令:

npm run build  # 使用 yarn 則是:yarn run build

執行完成後,同樣會構建出dist目錄及目錄下的程式文件。然後做個小實驗,執行下面的命令:

node dist/main.js

是不是發現,它同樣可以把我們的NestJS程式跑起來?其實,在通過構建後,dist目錄下的文件就是一個單獨可拿出去發布的東西了(其實還有package.json),把dist目錄以及package.json複製到其他的電腦上,就可以把這個程式完整的運行起來(當然別忘了先通過npm或yarn安裝依賴)。

介紹以上的內容,是為了讓大家清楚的了解我們真正要發布的東西有哪些。我們要認識到,發布程式的時候,我們不可能把源程式碼都給到別人,讓他們從源程式碼來運行我們的程式,這不僅不方便,也不太符合商業利益。

打包成鏡像

下面,我們要真正開始用到Docker了!我們要為我們的項目中添加一些文件,讓我們的項目具有容器化發布的能力。

先添加一個.dockerignore文件,內容如下:

node_modules  src  test

這個文件的作用,有點像Git的.gitignore文件。它是用來在Docker打包鏡像複製文件的過程中,排除掉不需要複製的文件的。在這個文件中,排除了2部分的內容:

1.項目的源程式碼目錄、測試程式碼目錄

因為我們發布給別人的鏡像里並不需要它們。

2. node_moudues依賴包目錄

排除它,完全是為了避免作業系統不同的問題。試想一下,如果你本地開發機的作業系統是Windows的,你本地安裝的node_modules目錄中可能含有在安裝時編譯成跟當前作業系統密切關聯的addons,這種addons在鏡像作業系統中(一般都是Linux)沒有辦法運行,程式就會出錯。所以,node_modules依賴包一定要在打包鏡像的時候在鏡像裡面運行安裝,才能保證依賴包是符合鏡像所運行的作業系統的。

接著,要添加的文件是Dockerfile,Docker打包鏡像的描述文件:

# 使用基於Alpine Linux製作的Node.js 12.13版本的基礎鏡像  FROM node:12.13-alpine    # 設置鏡像的工作目錄是 /app  WORKDIR /app    # 複製源程式碼目錄內容到鏡像的 /app 目錄中去  #(會忽略掉.dockerignore中聲明的內容)  COPY . /app    # 在鏡像的工作目錄下執行下列命令:  # 1. 設置yarn源為淘寶鏡像源,加速依賴包下載  # 2. 執行yarn安裝package.json中的項目依賴  RUN yarn config set registry http://registry.npm.taobao.org/ &&       yarn    # 設置環境變數  ENV NODE_ENV=production    # 設置鏡像啟動後的容器對外暴露(外界可訪問)的埠  EXPOSE 3000    # 鏡像容器啟動時執行的命令  # 即使用node來執行NestJS編譯後的dist目錄下的main.js  CMD ["node", "dist/main.js"]

有了上面的2個文件後,我們就可以開始打包鏡像了。在我們的項目根目錄下,執行:

docker build -t myserver:v1 .

命令行上一陣閃爍,打包結束!趕緊執行一段命令來確認一下打包後的鏡像資訊:

docker images

我們看到剛剛打包的名為myserver,版本標記為v1,大小為488MB的鏡像。成功!

鏡像有了,那我們怎麼來運行這個鏡像,它真的能跟我們預期的那樣跑起來嗎?快來試試下面的命令:

#以後台守護進程的方式,運行在3000埠  docker run -d -p 3000:3000 myserver:v1

執行完畢,那怎麼來確認它真的已經跑起來了呢?docker ps 一下唄,如果你能在執行的結果列表裡發現這個myserver:v1的鏡像所產生的容器,則說明已經運行成功了:

docker ps

快去瀏覽器里打開 http://localhost:3000/ 看看那句既樸素又雅緻,讓人感到親切又興奮激動,好似來自遠方的朋友的熱情問候:Hello World!

發布鏡像

前面打包完成的myserver:v1,已經是一個可以到處發布的鏡像了。但是當前它還只是在你的電腦上呆著,怎麼能讓要使用它的其他人獲取到這個鏡像呢?這個就需要依靠鏡像倉庫了,就如我們的Dockerfile里那個 node:12.13-alpine 基礎鏡像,其實也是從遠程的鏡像倉庫伺服器上下載的,默認使用的是官方鏡像倉庫Docker Hub(https://hub.docker.com/)。我們可以在自己的伺服器上安裝docker registry,搭建一個自己的鏡像倉庫私服,保證企業內部授權用戶才能訪問。也可以使用一些第三方的雲倉庫,比如阿里雲的容器鏡像服務就挺好用的,上傳下載速度也不錯。

每個鏡像倉庫需要先登錄才能使用,所以,請先在你使用的鏡像倉庫服務方獲取必要的登錄帳號和密碼等資訊。然後登錄:

docker login --username=your_account your_registry.domain.com

登錄完成後,你就可以開始向倉庫中上傳鏡像了:

#鏡像設置別名,別名需要符合目標鏡像倉庫的規定  docker tag myserver:v1 registry.cn-shanghai.aliyuncs.com/moredist-test/myserver:v1    #上傳鏡像  docker push registry.cn-shanghai.aliyuncs.com/moredist-test/myserver:v1

成功執行後,本地的鏡像就被上傳到了鏡像倉庫伺服器上去了。

至此,其他有許可權訪問該鏡像倉庫的人,就可以拉取你的程式鏡像,並把鏡像運行在任何安裝了Docker的電腦上了。拉取鏡像(未登錄過的需要先登錄):

docker pull registry.cn-shanghai.aliyuncs.com/moredist-test/myserver:v1

總結

我們花了一定的篇幅去介紹這種容器化的交付方式,並且乍一看還稍微有點工作量,但是這真的是一種非常值得你花點時間去學習的東西,這些投入,可以幫助你在以後的工作中有更高效、更優質的產出,如果藉助於一些CI/CD工具(比如Jenkins、Gitlab等),可以為你和你的團隊減少很多的重複勞動和出錯的幾率,讓日常工作更輕鬆一些。同時,作為一個服務端開發人員,這些東西會讓你產生更廣闊的思考空間,得到更多的隱性能力提升。

加油吧,少年!

Tags: