使用Docker和Docker Compose改善Node.js的開發

2021-01-19 騰訊網

在過去的幾年中,Docker和Node.js都變得非常流行。對於開發人員來說利用這些新技術來改善自己的開發體驗很有必要,而且在此過程中還可以學習新技術。遵循"Coding到老,學習到老,折騰到老"的宗旨,本文我們將介紹將如何結合Node.js與Docker開改善開發人員體驗,包括使用docker build和利用Docker Compose來實現無縫的本地前端開發環境。

概述

本文中,我們以Express.js為一個示例展開,需要實現了解一丁點Node.js和npm的基礎知識。還要了解Express.js框架的基礎知識。

對Docker也要有一定的概念和要會基礎操作(不會也沒關係,很容易)。

最後本文全程使用Linux(Mac) shell終端命令行。

創建Express.js項目

為了要生成示範應用程式,需要使用Express應用程式生成器。需要運行以下npx命令行:

npx express-generator --view=pug --git

Express生成器將生成Express應用。--view=pub選項表示使用pug視圖引擎。--git表示用來給項目添加一個git .gitignore文件。

生成效果如下:

測試Express應用

要測試該應用程式,需要運行npm install安裝所有必需的npm模塊。然後,運行以下命令以啟動應用程式:

如果沒有異常,應該會到一條類似的消息。

上面的命令非常簡單:它運行一個環境變量DEBUG=nodejs-docker-express,用來表示伺服器進行詳細的調試。

對Windows系統,使用的參數要修改為:

現在打開瀏覽器,在地址欄並輸入localhost:3000並訪問:

這樣示例的Express.js應用就已經在運行OK了。是不是非常簡單?有此基本的"Hello,World!"為基礎,我們進一步深入。

Docker多階段構建

容器化應用程式有很多好處:首先,無論運行平臺是什麼,其行為都相同。藉助Docker容器,應用程式可以輕鬆部署到各個公有容器雲(比如AWS Fargate,Google Cloud Run),自建的K8S集群中,甚至本地docker上。

容器化,基礎是Dockerfile。Dockerfile是構建Docker鏡像的基礎。用Dockerfile編譯生成的鏡像運行時,就稱之為容器。

如圖示,整個過程非常簡單:從Dockerfile構建Docker鏡像。運行鏡像,得到運行時容器。

Dockerfile

Dockerfile有一些類似命令行的語句:

WORKDIR語句設置了Docker運行的工作目錄,其後的命令都在該工作目錄運行。COPY語句,複製package*.json(package.json和package-lock.json)容器中。

EXPOSE語句,設置Node.js Express Web伺服器的監聽埠。上述步驟對於開發和生產階段都是通用的。

現在我們來看看生產目標階段是如何構建的。

production

在生產階段,繼續從基礎階段開始的工作,FROM語句指示Docker從base開始。ENV語句設置Docker將環境變量NODE_ENV為production。

變量ENV設置為production可以使性能提高三倍,並且提供一些其他優化,比如緩存視圖。npm install命令只會安裝主要依賴項,忽略開發依賴項。這些設置非常適合生產環境。

接著使用RUN語句運行npm ci而非npm install。npm ci適用於持續集成和部署。和npm install相比,會繞過某些面向用戶的功能。當然,npm ci需要一個package-lock.json文件才能工作。

之後,還是使用COPY語句將代碼複製到工作目錄。

最後使用CMD語句,運行Node應用伺服器和/srcbin/www

dev

我們利用了多階段構建,並在開發階段添加開發所需的組件:

大體上和生產極端類似,差異為NODE_ENV環境變量設置為development。

接著,用RUN語句安裝nodemon。每當文件更改時,nodemon都會重新啟動伺服器,從而開發體驗更加流暢。同時執行npm install,該命令會遞歸安裝dev依賴項。例如,如果要使用Jest測試應用程式,那將是開發依賴項之一。

請注意,這兩個命令通過&&放在一起,創建更少的Docker層,於構建緩存非常有用。這是撰寫Dockerfile時候常用的一個技巧。

和生產階段相同,將代碼複製到容器。但是,用nodemon取代了Node伺服器,這樣在每次文件/src更改時會重新啟動。

.dockerignore

和git的.gitignore一樣,docker也使用.dockerignore來忽略不想放入Docker鏡像的文件。通過忽略無關的文件更改,它有助於使Docker鏡像保持身材,而且能使構建緩存更高效。本示例中.dockerignore

非常簡單,告訴Docker不COPY.git文件夾和node_modules從主機複製到Docker容器。

使用Docker Compose

到目前為止,我們創建一個使用運行Node.js Express應用程式Docker所需的大部分功能。為了更便捷,我們還建議用Docker Compose,這樣可以更輕鬆地使用單個或多個容器運行應用程式。這樣也無需要記住很長的命令來構建或運行容器。只需通過:

但是docker-compose使用yml的配置文件和dockerfile略有不同:

上述,我們指定Docker Compose的版本,在本例中為3.8,對應Docker引擎19.0.3支持的最新版本。這樣可以支持多階段Docker構建。

接著,指定正在使用的服務。在本教程中,只有一個名為web的服務,具有context為當前目錄的構建以及一個重要的構建參數target設置為dev。這告訴Docker在dev階段構建Docker映像。

之後,通過volumes制定 Docker卷。它指示Docker從Docker容器上的./和主機本地/src目錄複製和同步更改。當我們在主機中更改文件時,這將很有用,並且文件也將立即反映到容器中。

command語句運行npm run start:dev,start:dev執行內容定義在package.json,內容為:

表示使用nodemon啟動Web伺服器。在開發環境中,可以在每次保存文件時重新啟動伺服器。

接下來,用ports語句設置docker埠映射主機的3000埠與容器3000埠。在構建容器時,公開了埠3000, Web伺服器就會在3000上運行。

最後,設置了兩個環境變量。首先,將其NODE_ENV設置為development,因為這樣可以看到詳細的Debug信息,也沒有任何視圖緩存。然後,將debug設置為*,讓Web伺服器列印出所有內容的詳細調試消息。

測試應用程式

前面,設置了弄好了基礎構建配置文件,接著構建Docker鏡像。使用BuildKit優化Docker構建。啟用BuildKit可以更快地構建Docker鏡像,運行以下命令:

該命令告訴Compose在BuildKit上構建Docker鏡像。它應該在一段時間內運行並構建Docker鏡像,如下所示:

Docker鏡像大約在14秒內構建完成,使用BuildKit可以更快。運行該鏡像:

然後瀏覽器訪問localhost:3000:

這樣我們,自配置的應用程式在Docker上已經完美運行。我們來改改源文件,看看效果。

我們修改下源碼將" Welcome to Express"更改為" Welcome to Express with Docker"來測試。在源文件目錄/src下,找到routes/index.jsline文件,修改語句為:

保存文件,然後可以看到Web伺服器已經重新啟動,表示Docker卷和nodemon可以都可以正常工作。

F5刷新瀏覽器,內容已經修改:

總結

本文中我們利用Docker和Docker Compose構建了一個簡單的Nodejs的開發和運行環境。Node.js和docker的配合很好。通過使用docker-compose,開發體驗更加流暢。當然這這是一個很簡單的開始,對於更複雜的應用(比如需要訪問資料庫)才是Docker Compose的用武之地,他可以同時啟動和管理多個容器,比如給開發環境增加Mongo或MySQL添加為應用程式的數據源,只需很輕鬆地增加一個docker-compose配置的服務語句就可以搞定整個環境。

相關焦點

  • 雲計算核心技術Docker教程:Docker Compose的restart和rm命令詳解
    Docker-Compose restart命令可以重新啟動所有已停止並正在運行的服務,Docker-Compose rm命令可以刪除已經停止的容器,如果服務在運行,需要先docker-compose stop 停止容器。
  • 用Jenkins、Docker部署 Serverless
    近日,使用 Serverless 開發了一個應用。其中 CI/CD,是需要考慮的一個問題。這裡用到了 Jenkins 和 Docker。並且 Jenkins Pipeline 運行在容器中。本文將介紹如何使用 Jenkins 和 Docker 構建並部署 Serverless 應用。
  • Docker 入門教程
    它能讓你將運行環境和配置放在代碼匯總然後部署, 同一個Docker的配置可以在不同的環境環境中使用, 這樣就降低了硬體要求和應用環境之間耦合度.2.代碼流水線管理代碼從開發者的機器到最終在生產環境上的部署, 需要經過很多的中堅環境.
  • docker下高並發和高可用之docker swarm使用
    ,操作步驟參考Linux下安裝和使用Docker安裝完,使用命令sudo systemctl start docker啟動docker,再通過命令Manager節點查看當前虛擬機節點的node信息docker node ls
  • SpringBoot+GitLab+Docker+Jenkins實現持續集成上
    鏡像: sameersbn/docker-gitlab鏡像可以快速實現部署並使用,適合於熟悉Docker的人使用,入門很快。下載GitLab鏡像如果我們直接使用Docker的鏡像方式去安裝GitLab,我們還必須手動安裝一些相關軟體,例如:Redis,PostgreSql。我們這次選用docker-compose的方式去安裝gitlab。
  • 30分鐘帶你了解Web工程師必知的Docker知識
    首先筆者先來介紹一下Docker:Docker 是一個基於 Go 語言開發的開源應用容器引擎, 可以讓我們把我們的應用和包打包到一個輕量級、可移植的容器中,然後發布到任何流行的 Linux 機器上,並且可以實現虛擬化。所謂容器,就是完全使用沙箱機制,相互之間沒有任何接口,並且性能開銷極低。
  • 雲計算核心技術Docker教程:Docker多階段構建
    多階段構建是一項新功能,需要守護程序和客戶端上使用Docker 17.05或更高版本。多級構建對於在優化Dockerfile的同時使其易於閱讀和維護的任何人都非常有用。
  • Docker常用命令就該這麼學!
    容器是完全使用沙箱機制,相互之間不會有任何接口。Docker 是一個用於開發,交付和運行應用程式的開放平臺。Docker 使您能夠將應用程式與基礎架構分開,從而可以快速交付軟體。 藉助 Docker,您可以與管理應用程式相同的方式來管理基礎架構。通過利用 Docker 的方法來快速交付,測試和部署代碼,您可以大大減少編寫代碼和在生產環境中運行代碼之間的延遲。
  • 雲計算核心技術Docker教程:Docker 守護進程dockerd的LCOW選項
    可以使用帶有--storage-opt標誌指定的選項來配置特定的存儲驅動程序 。lcow.globalmode指定守護程序是根據需要實例化實用程序VM實例(建議使用默認值,如果省略則默認),還是使用單個全局實用程序VM(性能更好,但具有安全隱患,不建議用於生產部署)。
  • 手把手教你利用Docker+jenkins部署你的網站
    更新伺服器的安裝源為阿里的源,參考連結:https://blog.csdn.net/js_xh/article/details/79166655安裝docker;1 更新資源可以用這個來驗證是否安裝成功了註:需要外網訪問則需要在雲服務哪裡設置安全組規則開放6379埠伺服器安裝jdk以及maven準備好jdk的包和maven包
  • NET微服務在Docker下打包部署及運行
    本文將和大家介紹利用ASP.NET Core 3.1搭建的WebAPI服務站點如何使用Docker打包,運行容器並提供外網訪問。#ENV :配置系統環境變量,比如程序環境環境等在這裡配置(開發、預發、線上環境)#這裡是配置程序運行埠,如果程序不使用默認的80埠這裡一定要設置(程序運行埠)ENV ASPNETCORE_URLS
  • Docker+jenkins小知識,講解通俗易懂,有必要收藏
    持續集成是軟體開發中一個非常重要的環節,我們都知道持續集成的這種方式,不僅僅是影響軟體開發的效率,實際上還會對我們軟體開發的流程會產生一定的影響,例如:我們所選擇的構建的方式,那麼你的應用程式的部署的方式,軟體開發與測試需要不斷地對應用進行持續構建,這些都會受我們持續集成的構建的方案所影響。
  • SpringBoot+GitLab+Docker+Jenkins實現持續集成下
    編寫SpringBoot項目Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。
  • jenkins 容器版安裝docker命令
    jenkins容器版裡docker自動安裝一直沒有成功,也可能是網絡原因,只能手動安裝docker命令,不然無法build和push。由於docker容器內的進程是以普通用戶啟動的,所以進入容器要指定root,不然無法安裝程序。
  • 雲計算核心技術Docker教程:Docker 守護進程dockerd節點發現
    dockerd --cluster-advertise選項指定 此特定守護程序實例在向集群發布自身時應使用的host:port或interface:port組合。遠程主機通過該值訪問守護程序。如果指定接口,請確保它包含實際Docker主機的IP位址。
  • 「Mysql」資料庫主從搭建-基於docker
    主從搭建的世界 :)通過Docker搭建主從伺服器首先我們需要拉取docker鏡像,我們使用5.7版本的MySQL:docker pull mysql:5.7然後使用此鏡像啟動容器,這裡需要分別啟動主從兩個容器創建Master(主資料庫):docker run
  • Docker容器固定IP分配詳解
    2021-01-12 11:28:51 來源: 西崑雲 舉報   我們在使用
  • 通過Docker安裝谷歌足球遊戲環境
    開發者在筆記本上編譯測試通過的容器可以批量地在生產環境中部署,包括VMs(虛擬機)、bare metal、OpenStack 集群和其他的基礎應用平臺。簡單來說,谷歌提供了包含安裝足球環境所需的必要環境在一個Docker配置文件中,安裝好Docker後,一條命令就可以創建包含足球環境的整套配置的Docker容器。通過容器可以直接進入安裝好足球環境的「虛擬」系統中。
  • 雲計算核心技術Docker教程:rm/rmi命令詳解
    在docker客戶端命令行中我們可以使用rm刪除一個或多個容器,使用rmi刪除本地一個或多少鏡像。示例:docker rm :刪除一個或多個容器。例如,強制刪除容器 db01、db02,命令如下:$ docker rm -f db01 db02移除容器 nginx01 對容器 db01 的連接,連接名 db:$ docker rm -l db刪除容器
  • 快速製作Redis Docker鏡像
    在國內的鏡像源直接下載壓縮包即可:https://mirrors.aliyun.com/alpine/v3.12/releases/x86_64/alpine-minirootfs-3.12.1-x86_64.tar.gz 當然docker