使用容器進行 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. server 服務下新增 secrets 區段,以便您的應用程式安全地處理資料庫密碼。 以下是更新後的 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. 開啟瀏覽器並確認應用程式正在 http://localhost:3000 執行。

  12. 將一些項目新增到待辦事項清單以測試資料保存。

  13. 將一些項目新增到待辦事項清單後,在終端機中按 ctrl+c 以停止您的應用程式。

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

    $ docker compose rm
    
  15. 執行 docker compose up 以再次執行您的應用程式。

    $ docker compose up --build
    
  16. 在您的瀏覽器中重新整理 http://localhost: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 中,您首先將標籤 as base 新增到 FROM node:${NODE_VERSION}-alpine 陳述式。 這讓您可以在其他建置階段參考此建置階段。 接著,您新增一個標記為 dev 的新建置階段,以安裝您的開發依賴項並使用 npm run dev 啟動容器。 最後,您新增一個標記為 prod 的階段,該階段省略開發依賴項並使用 node src/index.js 執行您的應用程式。 要瞭解更多關於多階段建置的資訊,請參閱 多階段建置

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

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

要使用 Compose 執行 dev 階段,您需要更新您的 compose.yaml 檔案。 在 IDE 或文字編輯器中開啟您的 compose.yaml 檔案,然後新增 target: dev 說明以從您的多階段 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

開啟瀏覽器並確認應用程式正在 http://localhost:3000 執行。

現在,您在本機電腦上對應用程式原始碼檔案所做的任何變更,都會立即反映在執行的容器中。

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

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

在您的瀏覽器中重新整理 http://localhost:3000,並確認更新後的文字已顯示。

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

摘要

在本節中,您了解了如何設定 Compose 檔案來新增模擬資料庫並保存資料。您還學習了如何建立多階段 Dockerfile,以及如何設定繫結掛載以進行開發。

相關資訊

後續步驟

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