使用容器進行 Node.js 開發

先決條件

完成 將 Node.js 應用程式容器化.

概述

在本節中,您將學習如何為您的容器化應用程式設定開發環境。這包括

  • 新增本地資料庫並持久化資料
  • 配置您的容器以執行開發環境
  • 除錯您的容器化應用程式

新增本地資料庫並持久化資料

您可以使用容器來設定本地服務,例如資料庫。在本節中,您將更新 compose.yaml 檔案以定義資料庫服務和捲來持久化資料。

  1. 在 IDE 或文字編輯器中開啟您的 compose.yaml 檔案。

  2. 取消註釋與資料庫相關的說明。以下是更新後的 compose.yaml 檔案。

    重要

    在本節中,請勿執行 docker compose up,直到您被告知為止。在中間點執行該命令可能會錯誤地初始化您的資料庫。

    compose.yaml
    # Comments are provided throughout this file to help you get started.
    # If you need more help, visit the Docker Compose reference guide at
    # https://docs.docker.net.tw/go/compose-spec-reference/
    
    # Here the instructions define your application as a service called "server".
    # This service is built from the Dockerfile in the current directory.
    # You can add other services your application may depend on here, such as a
    # database or a cache. For examples, see the Awesome Compose repository:
    # https://github.com/docker/awesome-compose
    services:
      server:
        build:
          context: .
        environment:
          NODE_ENV: production
        ports:
          - 3000:3000
    
    # The commented out section below is an example of how to define a PostgreSQL
    # database that your application can use. `depends_on` tells Docker Compose to
    # start the database before your application. The `db-data` volume persists the
    # database data between container restarts. The `db-password` secret is used
    # to set the database password. You must create `db/password.txt` and add
    # a password of your choosing to it before running `docker-compose up`.
    
        depends_on:
          db:
            condition: service_healthy
      db:
        image: postgres
        restart: always
        user: postgres
        secrets:
          - db-password
        volumes:
          - db-data:/var/lib/postgresql/data
        environment:
          - POSTGRES_DB=example
          - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
        expose:
          - 5432
        healthcheck:
          test: [ "CMD", "pg_isready" ]
          interval: 10s
          timeout: 5s
          retries: 5
    volumes:
      db-data:
    secrets:
      db-password:
        file: db/password.txt

    注意

    要詳細瞭解 Compose 檔案中的說明,請參閱 Compose 檔案參考.

  3. 在 IDE 或文字編輯器中開啟 src/persistence/postgres.js。您會注意到,此應用程式使用 Postgres 資料庫,需要一些環境變數才能連線到資料庫。compose.yaml 檔案中尚未定義這些變數。

  4. 新增指定資料庫配置的環境變數。以下是更新後的 compose.yaml 檔案。

    compose.yaml
    # Comments are provided throughout this file to help you get started.
    # If you need more help, visit the Docker Compose reference guide at
    # https://docs.docker.net.tw/go/compose-spec-reference/
    
    # Here the instructions define your application as a service called "server".
    # This service is built from the Dockerfile in the current directory.
    # You can add other services your application may depend on here, such as a
    # database or a cache. For examples, see the Awesome Compose repository:
    # https://github.com/docker/awesome-compose
    services:
      server:
        build:
          context: .
        environment:
          NODE_ENV: production
          POSTGRES_HOST: db
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD_FILE: /run/secrets/db-password
          POSTGRES_DB: example
        ports:
          - 3000:3000
    
    # The commented out section below is an example of how to define a PostgreSQL
    # database that your application can use. `depends_on` tells Docker Compose to
    # start the database before your application. The `db-data` volume persists the
    # database data between container restarts. The `db-password` secret is used
    # to set the database password. You must create `db/password.txt` and add
    # a password of your choosing to it before running `docker-compose up`.
    
        depends_on:
          db:
            condition: service_healthy
      db:
        image: postgres
        restart: always
        user: postgres
        secrets:
          - db-password
        volumes:
          - db-data:/var/lib/postgresql/data
        environment:
          - POSTGRES_DB=example
          - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
        expose:
          - 5432
        healthcheck:
          test: [ "CMD", "pg_isready" ]
          interval: 10s
          timeout: 5s
          retries: 5
    volumes:
      db-data:
    secrets:
      db-password:
        file: db/password.txt
  5. secrets 部分新增到 server 服務下,以便您的應用程式安全地處理資料庫密碼。以下是更新後的 compose.yaml 檔案。

    compose.yaml
    # Comments are provided throughout this file to help you get started.
    # If you need more help, visit the Docker Compose reference guide at
    # https://docs.docker.net.tw/go/compose-spec-reference/
    
    # Here the instructions define your application as a service called "server".
    # This service is built from the Dockerfile in the current directory.
    # You can add other services your application may depend on here, such as a
    # database or a cache. For examples, see the Awesome Compose repository:
    # https://github.com/docker/awesome-compose
    services:
      server:
        build:
          context: .
        environment:
          NODE_ENV: production
          POSTGRES_HOST: db
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD_FILE: /run/secrets/db-password
          POSTGRES_DB: example
        ports:
          - 3000:3000
    
    # The commented out section below is an example of how to define a PostgreSQL
    # database that your application can use. `depends_on` tells Docker Compose to
    # start the database before your application. The `db-data` volume persists the
    # database data between container restarts. The `db-password` secret is used
    # to set the database password. You must create `db/password.txt` and add
    # a password of your choosing to it before running `docker-compose up`.
    
        depends_on:
          db:
            condition: service_healthy
        secrets:
          - db-password
      db:
        image: postgres
        restart: always
        user: postgres
        secrets:
          - db-password
        volumes:
          - db-data:/var/lib/postgresql/data
        environment:
          - POSTGRES_DB=example
          - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
        expose:
          - 5432
        healthcheck:
          test: [ "CMD", "pg_isready" ]
          interval: 10s
          timeout: 5s
          retries: 5
    volumes:
      db-data:
    secrets:
      db-password:
        file: db/password.txt
  6. docker-nodejs-sample 目錄中,建立一個名為 db 的目錄。

  7. db 目錄中,建立一個名為 password.txt 的檔案。此檔案將包含您的資料庫密碼。

    您現在應該在 docker-nodejs-sample 目錄中至少有以下內容。

    ├── docker-nodejs-sample/
    │ ├── db/
    │ │ └── password.txt
    │ ├── spec/
    │ ├── src/
    │ ├── .dockerignore
    │ ├── .gitignore
    │ ├── compose.yaml
    │ ├── Dockerfile
    │ ├── package-lock.json
    │ ├── package.json
    │ └── README.md
  8. 在 IDE 或文字編輯器中開啟 password.txt 檔案,並指定您選擇的密碼。您的密碼必須在一行上,沒有其他行。確保檔案不包含任何換行符或其他隱藏字元。

  9. 確保儲存對您修改的所有檔案的更改。

  10. 執行以下命令啟動您的應用程式。

    $ docker compose up --build
    
  11. 開啟瀏覽器並驗證應用程式是否在 https://:3000 執行。

  12. 在待辦事項列表中新增一些專案以測試資料永續性。

  13. 在將一些專案新增到待辦事項列表後,在終端中按 ctrl+c 停止您的應用程式。

  14. 在終端中,執行 docker compose rm 刪除您的容器。

    $ docker compose rm
    
  15. 執行 docker compose up 重新執行您的應用程式。

    $ docker compose up --build
    
  16. 重新整理瀏覽器中的 https://:3000 並驗證待辦事項是否仍然存在,即使容器被刪除並再次執行。

配置和執行開發容器

您可以使用繫結掛載將原始碼掛載到容器中。然後,容器可以立即看到您對程式碼的更改,只要您儲存了一個檔案。這意味著您可以執行像 nodemon 這樣的程序,該程序在容器中監視檔案系統更改並對其進行響應。要詳細瞭解繫結掛載,請參閱 儲存概述.

除了新增繫結掛載之外,您還可以配置 Dockerfile 和 compose.yaml 檔案來安裝開發依賴項並執行開發工具。

更新您的 Dockerfile 以進行開發

在 IDE 或文字編輯器中開啟 Dockerfile。請注意,Dockerfile 不會安裝開發依賴項,也不會執行 nodemon。您需要更新 Dockerfile 以安裝開發依賴項並執行 nodemon。

與其為生產環境建立一個 Dockerfile,為開發環境建立另一個 Dockerfile,不如使用一個多階段 Dockerfile 用於兩者。

將您的 Dockerfile 更新為以下多階段 Dockerfile。

Dockerfile
# syntax=docker/dockerfile:1

ARG NODE_VERSION=18.0.0

FROM node:${NODE_VERSION}-alpine as base
WORKDIR /usr/src/app
EXPOSE 3000

FROM base as dev
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --include=dev
USER node
COPY . .
CMD npm run dev

FROM base as prod
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev
USER node
COPY . .
CMD node src/index.js

在 Dockerfile 中,您首先在 FROM node:${NODE_VERSION}-alpine 語句中新增一個標籤 as base。這使您可以在其他構建階段引用此構建階段。接下來,您新增一個名為 dev 的新構建階段來安裝您的開發依賴項並使用 npm run dev 啟動容器。最後,您新增一個名為 prod 的階段,該階段省略了開發依賴項,並使用 node src/index.js 執行您的應用程式。要詳細瞭解多階段構建,請參閱 多階段構建.

接下來,您需要更新 Compose 檔案以使用新階段。

更新您的 Compose 檔案以進行開發

要使用 Compose 執行 dev 階段,您需要更新您的 compose.yaml 檔案。在 IDE 或文字編輯器中開啟您的 compose.yaml 檔案,然後將 target: dev 指令新增到 target 以從多階段 Dockerfile 中定位 dev 階段。

此外,為繫結掛載將新卷新增到伺服器服務。對於此應用程式,您將從本地計算機上的 ./src 掛載到容器中的 /usr/src/app/src

最後,為除錯釋出埠 9229

以下是更新後的 Compose 檔案。所有註釋都已刪除。

compose.yaml
services:
  server:
    build:
      context: .
      target: dev
    ports:
      - 3000:3000
      - 9229:9229
    environment:
      NODE_ENV: production
      POSTGRES_HOST: db
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD_FILE: /run/secrets/db-password
      POSTGRES_DB: example
    depends_on:
      db:
        condition: service_healthy
    secrets:
      - db-password
    volumes:
      - ./src:/usr/src/app/src
  db:
    image: postgres
    restart: always
    user: postgres
    secrets:
      - db-password
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=example
      - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
    expose:
      - 5432
    healthcheck:
      test: [ "CMD", "pg_isready" ]
      interval: 10s
      timeout: 5s
      retries: 5
volumes:
  db-data:
secrets:
  db-password:
    file: db/password.txt

執行您的開發容器並除錯您的應用程式

執行以下命令,使用對 Dockerfilecompose.yaml 檔案的新更改執行您的應用程式。

$ docker compose up --build

開啟瀏覽器並驗證應用程式是否在 https://:3000 執行。

您對本地計算機上的應用程式原始檔的任何更改現在將立即反映在正在執行的容器中。

在 IDE 或文字編輯器中開啟 docker-nodejs-sample/src/static/js/app.js 並將第 109 行上的按鈕文字從 Add Item 更新為 Add

+                         {submitting ? 'Adding...' : 'Add'}
-                         {submitting ? 'Adding...' : 'Add Item'}

重新整理瀏覽器中的 https://:3000 並驗證更新後的文字是否顯示。

您現在可以將檢查器客戶端連線到您的應用程式以進行除錯。有關檢查器客戶端的更多詳細資訊,請參閱 Node.js 文件.

總結

在本節中,您瞭解瞭如何設定 Compose 檔案以新增模擬資料庫並持久化資料。您還學習瞭如何建立多階段 Dockerfile 以及如何為開發設定繫結掛載。

相關資訊

下一步

在下一節中,您將學習如何使用 Docker 執行單元測試。