1. 程式人生 > >實戰容器程式設計好基友之visual studio code+docker篇(二):實時除錯執行在docker中的node.js程式

實戰容器程式設計好基友之visual studio code+docker篇(二):實時除錯執行在docker中的node.js程式

上篇文章中,我們介紹了怎麼利用visual studio code在本地編譯生成docker映象,這篇文章我們會介紹怎麼利用Visual studio code 實時除錯執行在容器中的node.js程式。
這裡我們還會利用之前的專案node-todo, 環境搭建請參考上篇文章中的準備工作部分。
其實細心的同學會發現,在我們上篇文章中,通過vscode快捷命令新增dockerfile的時候,除了會新增dockerfile,docker-compose file還會新增一個docker-compose.debug.yml,這個是vscode新增的專門用來除錯的compose檔案,
這裡寫圖片描述
讓我們開啟這個檔案,就會看到如下配置:

version: '2'
services:
  node-todo:
    image:  node-todo:latest
    build:
      context: .
      dockerfile:  dockerfile
    environment:
NODE_ENV: development
MONGODB: {connectiongstring}
    ports:
      - 8080:8080
      - 5858:5858
    volumes:
      -  .:/usr/src/app
    command: node  --debug=5858 server.js

這裡,我們會看到它多開了一個埠號5858,這個就是我們用來remotedebug的埠號。
另外volumes引數把本地當前程式資料夾的內容覆蓋docker中的程式碼部署的路徑
最後compose中的command會覆蓋dockerfile中的command命令,通過debug=5858引數允許遠端除錯。這樣確保我們生成的映象是乾淨和一致的,因為我們不希望我們將映象部署到產品環境的時候也開啟除錯埠。
另外讓我們回過頭來再看下vscode幫我們生成的dockerfile

FROM node:4.2.3
COPY package.json /tmp/package.json
RUN cd /tmp && npm install --production
RUN mkdir -p /usr/src/app && mv /tmp/node_modules /usr/src WORKDIR /usr/src/app COPY . /usr/src/app EXPOSE 8080 CMD node server.js

這裡有兩點
1. 我們修改基礎的node 映象標籤用一個固定的版本號如4.2.3,這樣明確指定tag的好處是我們生成的映象總是一致的,避免因為dockerhub中映象升級,導致我們引入不同的基礎映象,造成生成映象的不一致。
2. 細心的同學會發現這段命令
RUN cd /tmp && npm install–production
RUN mkdir -p /usr/src/app && mv/tmp/node_modules /usr/src
它在tmp資料夾中通過npm安裝依賴,然後生成了一個檔案路徑/usr/src/app,下面用通過copy命令放置我們的程式程式碼。但是有意思的是它把依賴node_modules,放置到了/usr/src裡面,也就是說它把依賴放在程式資料夾的父資料夾中,而不是程式資料夾裡面。我們知道若沒有在require中指定路徑,nodejs 會在當前程式的父資料夾中尋找node_modules檔案。例如我們在/usr/src/app/server.js中通過require(‘express’)引用了express,那麼在啟動server.js時候,node.js總是會首先到/usr/src/app/node_modules, 然後去/usr/src/node_modules尋找依賴,並依次向上。那為什麼模版不把依賴放在/usr/src/app/裡面呢?這是因為我們在遠端除錯的時候會將本地的程式碼覆蓋docker中程式資料夾。如果依賴放在/usr/src/app/中,在遠端除錯就會被原生代碼覆蓋,所以這裡把依賴放在了上級目錄裡面。由此我們可以看到,我們要確保在/usr/src/app不包含node_modules,這樣它就可以到上級目錄尋找正確的依賴,這就要求我們
在生成映象的時候,本地程式資料夾中不包含依賴。
在我們遠端除錯的時候mount本地程式資料夾到docker裡面的路徑的時候,本地程式資料夾中也沒有node_module
這樣就避免了我們本機是mac/windows環境下載的依賴包,覆蓋了基於linux環境的docker中的依賴,帶來一些跨平臺的問題。

最後讓我們來配置這個專案的除錯環境.看專案檔案中,如果沒有/.vscode/launch.json,則直接按F5,選擇node.js,然後自動建立/.vscode/launch.json檔案,修改如下

{
    // Use  IntelliSense to learn about possible Node.js debug attributes.
    // Hover to view  descriptions of existing attributes.
    // For more  information, visit: https://go.microsoft.com/fwlink/?linkid=830387
     "version": "0.2.0",
     "configurations": [
        {
             "type": "node",
             "request": "launch",
             "name": "Launch Program",
             "program": "${workspaceRoot}/server.js",
             "cwd": "${workspaceRoot}",
             "restart": false
        },
        {
             "type": "node",
             "request": "attach",
             "name": "Attach to Process",
             "port": 5858,
             "address":"localhost",
             "localRoot": "${workspaceRoot}/",
"remoteRoot":"/usr/src/app/",
            "restart":  true
        }
    ]
}

這裡有兩部分,一部分是launchprogram主要是在本機除錯的時候用到,另外一部分是Attachto Process 是在在遠端編譯的時候用到,今天我們主要介紹attach部分,這裡要注意幾個配置
· Port,指定了除錯的埠號,與專案啟動後監聽的埠號是不同的
· Address,用來指定除錯的遠端主機的地址,如果docker 跑在本機可以用localhost,如果不是請用命令docker-machieip {機器名}獲取及其的ip地址後替換
· LocalRoot,用來指定原生代碼的地址,這裡我們用引數{workspaceRoot}用來指向當前vscode開啟的路徑。
· remoteRoot 遠端主機或者容器中程式碼執行的地址。
· restart, 指定當nodejs重啟時是否重新啟動debug,這個在後面會用到

在這些都配置好以後我們就可以開始除錯了。
首先通過shift+ command + P啟動快捷命令視窗,輸入docker: compose up, 選擇docker-compose.debug.yml檔案,然後我們會看到在terminial中的輸出
這裡寫圖片描述
我們會看到程式埠和除錯埠都已經在監聽。讓我們在route.js中打一個斷點,
這裡寫圖片描述
然後開啟vscode的除錯頁面,選擇attachto process ,
這裡寫圖片描述
按下f5,然後,然後用瀏覽器開啟http://localhost:8080,如果發現程式碼已經停留在我們的斷點處了,那麼恭喜你已經可以開始遠端除錯docker裡面的程式了。
這裡寫圖片描述
但是還有一個問題,就是如果我們修改了本地的程式碼,例如我們將頁面的標題改為“Thisis a test”,重新整理頁面發現我們的改動並沒有生效。難道我們在除錯的時候每次改動都要重新生成一遍映象嗎?這樣太麻煩了。這裡我們就需要引入一個工具nodemon,它會自動監視資料夾裡面的改動,然後重啟程序,具體改動如下:
1. 在docker file檔案中新增以下命令在全域性安裝nodemon
RUN npm install -g nodemon
2. 在docker-compose.debug.yml檔案中,將CMD中node啟動改為nodemon啟動,例如
command: nodemon --debug=5858 server.js
好的,把我們之前生成的docker通過命令docker rm –f $(docker ps -aq)刪除,重新通過快捷命令視窗啟動docker:compose up.這時我們在terminial中,會看到nodemon已經開始監控檔案變化
這裡寫圖片描述
這時我們再按f5就可以開始愉快的除錯,修改儲存後,nodemon會重啟nodejs程序,修改實時生效。還記得我們在vscode的launch.json中將attach部分的restart設成了true嗎?當nodemon重啟程序後,vscode也會重啟debugger重新attach,這樣就可以繼續除錯了
以上是我基於macos做的設定,對於使用windows作為開發平臺的同學,需要額外做兩件事
1. 在docker 的設定裡面要將放置程式碼的磁碟共享,這樣就可以將原生代碼mount到docker裡面
這裡寫圖片描述
2. 在compose檔案中nodemon 啟動命令時新增一個-L引數
command: nodemon --debug=5858 -L server.js
好的今天就介紹到這裡,大家在用vscode過程中有任何問題可以到github上https://github.com/Microsoft/vscode 和大家交流,Erich Gamma大神也經常在上面直接回答問題。