JavaScript >> Javascript 文檔 >  >> Node.js

使用 Docker 的容器中的 Node.js

容器技術是軟件開發和部署的最佳選擇之一。它允許您在封裝代碼和其他問題的同時共享一些操作系統資源。您可以將容器視為虛擬機,但佔用空間更少。

容器非常適合用許多服務替換單體應用的微服務。它們中的每一個都獨立工作,並通過定義明確的接口(通常是 REST)與其他服務進行通信。

Docker 是最流行的容器實現之一。 Docker 的 Docker 是什麼?頁面對容器與虛擬機進行了巧妙的比較。簡而言之,虛擬機使用虛擬機管理程序,每個虛擬機都有自己的操作系統,而容器共享操作系統,並且只有單獨的庫、bin、可執行文件等。

這是一個關於 VM 工作原理的簡化圖(來源:docker.com)。


使用容器時,可以共享更多內容。因此,您可以更快地啟動、執行、啟動等。


以下是 Docker 容器的一些好處:

  • 允許快速開發/部署應用程序。
  • 可擴展。
  • 輕巧。
  • 可跨機器和環境移植。
  • 速度快,佔地面積小。
  • 易於使用。
  • 允許從開發到生產的行為一致。
  • 可以進行版本控制,並且可以重複使用組件。
  • 允許社區/協作。
  • 易於維護。

在開始使用 Docker 之前,我們應該定義常用術語,即 Docker 生態系統中經常使用的術語:

圖片 – 構成容器基礎的應用程序藍圖。我們將使用 docker pull 命令下載指定圖片。

容器 – 從 Docker 映像創建並運行實際應用程序。我們使用 docker run 創建一個容器 .可以使用 docker ps 查看正在運行的容器列表 命令。

Docker 守護進程 – 在管理構建、運行和分發 Docker 容器的主機上運行的後台服務。守護進程是在客戶端與之交談的操作系統中運行的進程。這就是 Docker Engine 工作的原因。

Docker 客戶端 – 允許用戶與守護進程交互的命令行工具。可以有其他形式的客戶端——例如提供 GUI 的 Kitematic。

Docker 中心 – Docker 鏡像的註冊表。您可以將註冊表視為所有可用 Docker 映像的目錄。如果需要,可以託管自己的 Docker 註冊表,並可以使用它們來拉取鏡像。

Dockerfile – 您可以從中創建圖像的配方。 Dockerfile 具有基礎鏡像、添加或複製文件的指令、要執行的命令、要公開的端口和其他信息。 Dockerfile 區分大小寫。

Docker 編寫 – 從單個配置文件 docker-compose.yml 編排服務所需的多個容器的機制 .

[旁注]

閱讀博客文章很好,但觀看視頻課程更好,因為它們更具吸引力。

許多開發人員抱怨 Node.js 上缺乏負擔得起的高質量視頻材料。觀看 YouTube 視頻會讓人分心,花 500 美元購買 Node 視頻課程很瘋狂!

去看看 Node University,它有關於 Node 的免費視頻課程:node.university。

[旁注結束]

主機 – 託管 docker daemon 的計算機或託管 docker deamon/engine 的遠程計算機。

Node.js 是增長最快的平台之一。它非常適合 Web 應用程序和 API,尤其是微服務。讓我們看看如何通過這些步驟開始使用 Node 和 Docker:

  • 安裝 Docker
  • Docker 基礎知識
  • 創建節點圖像
  • 使用多個容器:Node 和 MongoDB

安裝 Docker

首先,您需要獲取 Docker 守護程序。如果你和我一樣是 macOS 用戶,那麼最簡單的方法就是訪問 Docker 官方網站 https://docs.docker.com/docker-for-mac。

如果您不是 macOS 用戶,則可以從此頁面中選擇一個選項:https://docs.docker.com/engine/installation。

安裝完成後,運行以下命令測試您的 Docker 安裝:

$ docker run hello-world

如果你看到這樣的消息很可能你沒有啟動 Docker:

Cannot connect to the Docker daemon. Is the docker daemon running on this host? 

啟動 Docker。如果您使用 macOS,則可以使用 GUI 應用程序。否則,CLI。

這是在我的 macOS 上運行 Docker 守護程序的外觀:


我什至可以配置它需要多少內存,是自動更新還是在登錄時自行啟動。

相反,如果您看到如下所示的消息,則說明 deamon 正在運行,您已準備好使用 Docker!

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
 
c04b14da8d14: Pull complete
Digest: sha256:0256e8a36e2070f7bf2d0b0763dbabdd67798512411de4cdcf9431a1feb60fd9
Status: Downloaded newer image for hello-world:latest
 
Hello from Docker!
This message shows that your installation appears to be working correctly.
 
...

接下來,我們將下載一個輕量級版本的 Linux 作為鏡像。它被稱為阿爾卑斯山。我們將從 Docker Hub 獲取這個 Alpine 鏡像。

$ docker pull alpine

等待圖像下載。我希望你有一個快速的互聯網速度。好消息是您只需要下載一次圖像。它將存儲在您的計算機上以供將來使用。讓我們實際繼續並通過運行檢查圖像是否存在:

$ docker images

它會告訴你阿爾卑斯山,你好世界,可能沒有別的了。沒關係,因為您剛剛開始使用 Docker。先來學習一下Docker基礎吧。

Docker 基礎知識

首先,要從 Docker Hub 安裝鏡像(拉取),有一個 docker pull {name} 命令。您已經將它用於 Alpine:

$ docker pull alpine

來自 Docker Hub 的其他一些圖像名稱如下:

  • boron :基於 Debian Jessie 的 Node.js v6
  • argon :基於 Debian Jessie 的 Node.js v4
  • ubuntu :Ubuntu
  • redis :基於 Debian Jessie 的 Redis
  • mongodb :基於 Debian Wheezy 的 MongoDB

下載圖像後,您可以使用 docker run {name} 運行它 ,例如,

$ docker run alpine

但後來什麼都沒有 發生了!那是因為當你調用 $ docker run {name} ,Docker客戶端(CLI):

  • 找到圖片(alpine 在這種情況下)
  • 加載容器
  • 在容器中運行命令(如果有)

當我們運行 $ docker run alpine ,我們沒有提供任何命令,所以容器啟動,運行一個空命令然後退出。

讓我們嘗試一個更好的命令來打印 hello world from alpine

$ docker run alpine echo "hello from alpine"

結果,Docker 在我們的 alpine 容器中運行 echo 命令,然後退出。

想像一下啟動虛擬機、在其中運行命令然後殺死它可能需要多長時間!比容器長得多。這是容器的好處。

如果是容器只能運行一個回顯命令並退出的情況,它們將非常無用。幸運的是,容器可以執行長時間運行的進程,即它們在不退出的情況下運行。要查看當前正在運行的所有容器,請使用以下命令:

$ docker ps

ps 將顯示我們在這台計算機(稱為主機)上運行的所有容器的列表:

$ docker ps -a

要停止分離的容器,請運行 $ docker stop {ID} 通過提供容器 ID。

doker run 的一些有用選項 命令是:

  • -d 將分離我們的終端(bg/daemon)。
  • -rm 運行後會移除容器。
  • -it 在容器中附加一個交互式 tty。
  • -p 將為我們的容器發布/公開端口。
  • --name 我們容器的名稱。
  • -v 掛載一個卷以在主機和容器之間共享。
  • -e 為容器提供環境變量。
  • docker run --help 適用於所有標誌

創建 Docker 映像

如果你還記得定義,有 Dockerfile 這樣的東西。這就是我們創建新圖像的方式。事實上,Docker Hub 上的每個鏡像都有 Dockerfile。 Dockerfile 只是一個文本文件,其中包含 Docker 客戶端在構建映像時調用的命令列表。

您可以在 Dockerfile 中包含以下說明:

  • 來自 :(作為文件中的第一條指令所必需)指定構建 Docker 容器的基礎鏡像,以及運行後續 Dockerfile 指令的基礎鏡像。
    鏡像可以託管在公共存儲庫中,也可以託管在私有存儲庫中通過第三方註冊中心或您在 EC2 上運行的存儲庫。

  • 曝光 :列出要在容器上公開的端口。

  • 添加 :將指定文件添加到容器上的某個位置

  • 工作目錄 :設置當前工作目錄以在容器中運行命令。

  • 音量 :將掛載點標記為主機(或其他容器)外部可用。

  • CMD :指定可執行文件和默認參數,它們組合成容器在啟動時運行的命令。使用以下格式:

    CMD ["executable","param1","param2"]
    

CMD 也可用於為 ENTRYPOINT 提供默認參數 命令通過省略可執行參數。必須在 CMD 中指定可執行文件 或 ENTRYPOINT ,但不是兩者兼而有之。對於基本場景,使用 CMD 並省略 ENTRYPOINT .

入口點 :使用與 CMD 相同的 JSON 格式 並且,像 CMD , 指定容器啟動時要運行的命令。還允許容器作為可執行文件運行 docker run。

如果您定義 ENTRYPOINT ,您也可以使用 CMD 來指定可以使用 docker run 的 -d 選項覆蓋的默認參數。 ENTRYPOINT 定義的命令 (包括任何參數)在容器運行時與來自 **CMD **或 docker run 的參數相結合。

運行 :指定一個或多個命令,用於在映像中安裝包和配置 Web 應用程序。

環境 – 設置環境變量{key} 到值 {value} 使用 {key}={value} .語法示例:

ENV myName="John Doe" myDog=Rex The Dog myCat=fluffy

有關說明的更多信息,您可以包含在 Dockerfile 中 ,請轉到 Dockerfile 參考:http://docs.docker.io/reference/builder。有關 Dockerfile 提示和最佳實踐:
https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices

卷可以在主機(您的計算機)和容器之間共享代碼。換句話說,Docker 卷是臨時 Docker 容器和主機之間的蟲洞。它非常適合開發或持久數據。以下命令將從主機上的當前工作目錄 (pwd) 掛載卷。這些文件將在 /www/ 中可用 在容器中。記住選項的方式是從左到右,即host:contaner .

$ docker run -v $(pwd)/:/www/ -it ubuntu

運行命令後,由於 -it,您將進入容器內部 .在那裡您可以導航到 /wwwcd /www .你看到了什麼(使用 ls )?你的文件!現在這就是魔法。如果您修改、刪除添加文件到您的主機文件夾,這些更改將自動在容器中!

而且,即使容器停止了,持久化的數據仍然存在於Docker主機上,並且可以訪問。

創建 Docker 節點映像

現在,當涉及到 Node 時,您可以選擇從 Docker Hub 獲取官方 Node 映像之一。當前版本是 Boron 和 Argon,但也有版本 7 和夜間版本。

另一種選擇是從 Debian 或 Ubuntu 基礎構建 Node 映像。您甚至不必自己編寫 Dockerfile。您可以從官方圖片中藉用幾行,並根據需要添加/刪除。

我們將繼續第一個選項,因為它是最簡單的方法。所以我們創建 Dockerfile 在您擁有 package.json 的 Node.js 項目文件夾中 和 node_modules ,即項目的根目錄。每個項目通常是一個文件夾,甚至是一個單獨的 Git 存儲庫。然後,寫入 Dockerfile 指令:

FROM node:argon
 
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
 
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
 
# Bundle app source
COPY . /usr/src/app
 
EXPOSE 3000
CMD [ "npm", "start" ]

我們從 Argon 圖像開始,為您的應用程序代碼創建一個文件夾。然後,我們從當前文件夾(項目根目錄)複製源代碼文件。最後,我們暴露了應用程序端口(出於某種奇怪的原因,它幾乎總是 3000)並使用 npm start 啟動服務器 假設您在 package.json 中定義了該 npm 腳本 .如果你不喜歡像 npm start 這樣的 npm 腳本 ,然後只需使用 node app.jsnode server.js 取決於你的文件名。

要構建 Node.js 應用映像,請運行 $ docker build . 如果您還沒有 Agron,那麼第一次運行它可能需要更長的時間。下一次,它會更快。構建完成後,您可以像運行任何其他鏡像一樣運行您的應用容器:

$ docker run {name}

這是一個問題。如果您只是使用 docker build,您可能已經註意到您的新圖像沒有名稱 .而且很可能,您已經擁有或將擁有多個圖像。因此,最好在構建圖像時命名和標記圖像。使用 -t 標誌和 nam:tag 格式。例如,

$ docker build -t {your-name}/{your-app-name}:{tag} .

容器速度很快,但每次更改源代碼時都構建新映像並不是很酷。因此,對於開發,我們可以將源代碼掛載為一個卷,並使用類似 forever 的東西 或 nodemonnode-dev 隨時按下保存來監聽文件更改並重新啟動服務器。如果是卷,則無需複制源代碼,因為它會從卷中掛載。

FROM node:argon
 
WORKDIR /usr/src/app 
RUN npm install

EXPOSE 3000
CMD [ "nodemon", "app.js" ]

運行此映像的命令會稍微提前一些,因為現在我們需要掛載卷:

$ docker run -v ./:/usr/src/app -it {name}

現在,您所做的更改將傳遞給容器,服務器將重新啟動,您可以在主機環境中進行開發,同時在容器中運行代碼。兩全其美! (這很棒,因為容器環境將是完全 在生產中與您現在擁有的相同。)但是應用程序不能自行運行。您需要一些持久性和其他服務。

使用多個容器:Node 和 MongoDB

version: '2'
services:
 
  mongo:
    image: mongo
    command: mongod --smallfiles
    networks:
      - all
 
  web:
    image: node:argon
    volumes:
      - ./:/usr/src/app
    working_dir: /usr/src/app
    command: sh -c 'npm install; npm run seed; npm start'
    ports:
      - "3000:8080"
    depends_on:
      - mongo
    networks:
      - all
    environment:
      MONGODB_URI: "mongodb://mongo:27017/accounts"
 
networks:
  all:

讓我們逐行檢查這個 ymp 文件。我們從服務列表開始。服務名稱,即mongodb 將在其他容器中可用,因此我們可以使用 mongodb://mongo:27017/accounts 連接到 MongoDB .您不必在環境變量中傳遞此連接字符串。我這樣做只是為了表明你可以做到。

鏡像、卷、端口和其他字段模仿 Dockerfile 指令。關鍵區別在於我們使用 depends_on .這將告訴 web 服務使用 mongo 服務。

要運行 Docker compose,只需執行以下終端命令(假設 deamon 正在運行):

$ docker-compose up

您可以在 https://github.com/azat-co/mern/blob/master/code 查看 MERN(MongoDB、Express、React 和 Node)應用程序的完整工作示例。 Docker compose 是啟動多容器環境的一種出色而簡單的方法。

總結

容器非常適合在多個環境中以很少的開銷安全地獲取您的代碼。這使您可以最大程度地減少任何差異。基本思想是,通過在與生產環境相同的環境中進行開發,您將消除與 dev 和 prod 之間的差異相關的任何潛在問題。此外,通過比虛擬機更便宜的封裝,我們可以將我們的應用程序拆分為更精細的服務。它們不僅可以分為應用程序、數據庫、緩存、Web 服務器,還可以進一步劃分。我們可以通過資源將 Web 應用程序拆分為容器,例如 /accounts 的端點 在一個容器中,/users 的端點 在另一個等等……但這是另一個帖子的主題。

進一步閱讀和 Docker 資源

學習永不止步!這裡有一些關於 Docker 的閱讀資料和資源。

  • 很棒的 Docker: https://github.com/veggiemonk/awesome-docker
  • 你好 Docker 研討會: http://docker.atbaker.me
  • 為什麼選擇 Docker: https://blog.codeship.com/why-docker
  • Docker 周刊和檔案: https://blog.docker.com/docker-weekly-archives
  • Codeship 博客: https://blog.codeship.com

PS:特色圖片中提到的AWS部分將在新帖子中介紹。


Tutorial JavaScript 教程
  1. 找出 JavaScript 數組中最大的日期

  2. 動態列表的水平滾動

  3. 100DaysOfCode 的第 10 天

  4. 套接字 IO 重新連接?

  5. 在基本的 Javascript 之後我應該學習什麼?

  6. 使用 React Native 2 的聊天應用程序 - 使用 react-native-firebase 實現電子郵件身份驗證

  7. 網址對象

  1. 我如何構建我的中型 NextJS 項目

  2. 大O

  3. 如何檢查變量是否是 JavaScript 中的數組

  4. 演示:禁用 JavaScript 不會讓您免於指紋識別

  5. 調整 CRM 站點地圖,為不同的環境提供不同的 URL 導航

  6. 迭代嵌套數組項,並根據特定鍵的相同值,收集任何其他條目值作為按鍵+值分組的合併數據

  7. 我在 React.js 中創建了一個電子郵件生成器,它需要轉換為像 stripo 或 unlayer 這樣的插件或庫

  1. 2020 年最佳靜態站點生成器

  2. 為什麼你應該在 2021 年學習 Javascript!

  3. 補液的危險:關於 Gatsby 和 React 的令人大開眼界的認識

  4. 使用 React 和 JavaScript 構建您自己的 Google Like Autocomplete