教學課程:使用 MySQL 和 Docker Compose 建立多容器應用程式

在本教學課程中,您將了解如何建立多容器應用程式。 本教學課程是以使用者入門教學課程開始使用 Docker 和 Visual Studio Code 為基礎。 在本進階教學課程中,您將更新應用程式,以如此圖表所述運作,並了解如何:

  • 啟動 MySQL。
  • 使用 MySQL 執行您的應用程式。
  • 建立撰寫檔案。
  • 執行應用程式堆疊。

Diagram shows two containers labeled Todo App and MySQL connected with a line.

使用多個容器可讓您將容器專用於特製化工作。 每個容器都應該執行一項操作並妥善處理。

以下是您可能需要使用多容器應用程式的一些原因:

  • 將容器分開,以不同於資料庫的方式管理 API 和前端。
  • 容器可讓您以隔離的方式設定版本及更新版本。
  • 雖然您可能會在本機使用資料庫的容器,但您可能需要針對生產中的資料庫使用受控服務。
  • 執行多個處理序需要處理序管理員,這會增加容器啟動/關機的複雜性。

必要條件

本教學課程會繼續進行一系列教學課程,從建立容器應用程式開始。 從這一項開始,其中包含必要條件。 然後執行教學課程在應用程式中保存資料

您也需要下列項目:

  • Docker Compose

    適用於 Windows 或 Mac 的 Docker Desktop 包含 Docker Compose。 執行此命令以確認:

    docker-compose version
    

    如果您使用 Linux 作業系統,請安裝 Docker Compose

如同先前的教學課程,您可以從 VS Code EXPLORER 檢視或 DOCKER 檢視完成大部分工作。 您可以選取 [終端機]>[新終端機],以在 VS Code 中開啟命令列視窗。 您也可以在 Bash 視窗中執行命令。 除非指定,否則標示為 Bash 的任何命令都可以在 Bash 視窗或 VS Code 終端機中執行。

啟動 MySQL

根據預設,容器會以隔離方式執行。 各容器不知道同一部電腦上的其他處理序或容器。 若要允許一個容器與另一個容器交談,請使用網路功能。

如果兩個容器位於相同的網路上,其可以彼此交談。 如果容器不是位於相同的網路上,則無法彼此交談。

有兩種方式可將容器放在網路上:在啟動時指派容器,或連線現有的容器。 在此範例中,您會先建立網路,並在啟動時連結 MySQL 容器。

  1. 使用此命令建立網路。

    docker network create todo-app
    
  2. 啟動 MySQL 容器,並將其連結至網路。

    docker run -d 
        --network todo-app --network-alias mysql 
        -v todo-mysql-data:/var/lib/mysql 
        -e MYSQL_ROOT_PASSWORD=<your-password> 
        -e MYSQL_DATABASE=todos 
        mysql:5.7
    

    此命令也會定義環境變數。 如需詳細資訊,請參閱 MySQL Docker Hub 清單

    命令會指定網路別名 mysql

  3. 使用 docker ps 命令取得容器識別碼。

  4. 若要確認資料庫已啟動並執行,請連線到資料庫。

    docker exec -it <mysql-container-id> mysql -p
    

    出現提示時,請輸入您在上方所使用的密碼。

  5. 在 MySQL 殼層中,列出資料庫,並確認您看到 todos 資料庫。

    SHOW DATABASES;
    

    您應該會看見下列輸出。

    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sys                |
    | todos              |
    +--------------------+
    5 rows in set (0.00 sec)
    
  6. 當您準備好返回終端機命令提示字元時,請輸入 exit

使用 MySQL 執行您的應用程式

Todo 應用程式支援環境變數的設定,以指定 MySQL 連線設定。

  • MYSQL_HOST MySQL 伺服器的主機名稱。
  • MYSQL_USER 要用於連線的使用者名稱。
  • MYSQL_PASSWORD 要用於連線的密碼。
  • MYSQL_DB 連線後要使用的資料庫。

警告

使用環境變數來設定連線設定為可接受進行開發。 建議針對在生產環境中執行應用程式的做法。 如需詳細資訊,請參閱為何您不應該將環境變數用於秘密資料

更安全的機制是使用容器協調流程架構所提供的秘密支援。 在大部分情況下,這些秘密會掛接為執行中容器內的檔案。

此程序會啟動您的應用程式,並將該容器連線到 MySQL 容器。

  1. 使用下列 docker run 命令。 其會指定上述環境變數。

    docker run -dp 3000:3000 
      -w /app -v ${PWD}:/app 
      --network todo-app 
      -e MYSQL_HOST=mysql 
      -e MYSQL_USER=root 
      -e MYSQL_PASSWORD=<your-password> 
      -e MYSQL_DB=todos 
      node:20-alpine 
      sh -c "yarn install && yarn run dev"
    
  2. 在 VS Code 的 Docker 檢視中,以滑鼠右鍵按一下應用程式容器,然後選取 [檢視記錄]。 若要從命令列檢視記錄,請使用 docker logs 命令。

    結果包含一行,指出應用程式已連線到 MySQL 資料庫。

    # Previous log messages omitted
    $ nodemon src/index.js
    [nodemon] 1.19.2
    [nodemon] to restart at any time, enter `rs`
    [nodemon] watching dir(s): *.*
    [nodemon] starting `node src/index.js`
    Connected to mysql db at host mysql
    Listening on port 3000
    
  3. 輸入您的 http://localhost:3000 瀏覽器。 將一些項目新增至您的 Todo 清單。

  4. 如同您在上一節中所做的一樣,連線到 MySQL 資料庫。 執行此命令,以確認項目正在寫入資料庫。

    docker exec -ti <mysql-container-id> mysql -p todos
    

    在 MySQL 殼層中,執行下列命令。

    use todos;
    select * from todo_items;
    

    您的結果看起來會像下列輸出。

    +--------------------------------------+--------------------+-----------+
    | id                                   | name               | completed |
    +--------------------------------------+--------------------+-----------+
    | c906ff08-60e6-44e6-8f49-ed56a0853e85 | Do amazing things! |         0 |
    | 2912a79e-8486-4bc3-a4c5-460793a575ab | Be awesome!        |         0 |
    +--------------------------------------+--------------------+-----------+
    

此時,您有一個應用程式會將資料儲存在外部資料庫中。 該資料庫會在個別的容器中執行。 您已了解容器網路功能。

建立 Docker Compose 檔案

Docker Compose 可協助定義及共用多容器應用程式。 使用 Docker Compose,您可以建立檔案來定義服務。 您可以使用單一命令來啟動所有項目,或將其全部拆毀。

您可以在檔案中定義應用程式堆疊,並在版本控制下,將該檔案保留在專案存放庫的根目錄。 此方法可讓其他人參與您的專案。 他們只需要複製您的存放庫。

  1. 在應用程式專案的根目錄中,建立名為 docker-compose.yml 的檔案。

  2. 在撰寫檔案中,從定義結構描述版本開始。

    version: "3.7"
    

    在大部分情況下,最好使用最新的支援版本。 如需目前的結構描述版本和相容性矩陣,請參閱撰寫檔案

  3. 定義您要做為應用程式一部分執行的服務或容器。

    version: "3.7"
    
    services:
    

    提示

    縮排在 .yml 檔案中很重要。 如果您要在 VS Code 中進行編輯,Intellisense 表示錯誤。

  4. 以下是您用於應用程式容器的命令。 您會將此資訊新增至 .yml 檔案。

    docker run -dp 3000:3000 
      -w /app -v ${PWD}:/app 
      --network todo-app 
      -e MYSQL_HOST=mysql 
      -e MYSQL_USER=root 
      -e MYSQL_PASSWORD=<your-password> 
      -e MYSQL_DB=todos 
      node:20-alpine 
      sh -c "yarn install && yarn run dev"
    

    定義容器的服務項目和映像。

    version: "3.7"
    
    services:
      app:
        image: node:20-alpine
    

    您可以為服務挑選任何名稱。 名稱會自動變成網路別名,這在定義 MySQL 服務時很有用。

  5. 新增命令。

    version: "3.7"
    
    services:
      app:
        image: node:20-alpine
        command: sh -c "yarn install && yarn run dev"
    
  6. 指定服務的連接埠,此連接埠會對應至上述命令中的 -p 3000:3000

    version: "3.7"
    
    services:
      app:
        image: node:20-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 3000:3000
    
  7. 指定工作目錄和磁碟區對應

    version: "3.7"
    
    services:
      app:
        image: node:20-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 3000:3000
        working_dir: /app
        volumes:
          - ./:/app
    

    在 Docker Compose 磁碟區定義中,您可以使用來自目前目錄的相對路徑。

  8. 指定環境變數定義。

    version: "3.7"
    
    services:
      app:
        image: node:20-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 3000:3000
        working_dir: /app
        volumes:
          - ./:/app
        environment:
          MYSQL_HOST: mysql
          MYSQL_USER: root
          MYSQL_PASSWORD: <your-password>
          MYSQL_DB: todos
    
  9. 新增 MySQL 服務的定義。 以下是您在上方使用的命令:

    docker run -d 
      --network todo-app --network-alias mysql 
      -v todo-mysql-data:/var/lib/mysql 
      -e MYSQL_ROOT_PASSWORD=<your-password> 
      -e MYSQL_DATABASE=todos 
      mysql:5.7
    

    定義新的服務,並將其命名為 mysql。 在 app 定義之後,在相同層級的縮排中新增您的文字。

    version: "3.7"
    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:5.7
    

    服務會自動取得網路別名。 指定要使用的映像。

  10. 定義磁碟區對應。

    使用與 services: 相同層級的 volumes: 區段指定磁碟區。 指定映像下的磁碟區對應。

    version: "3.7"
    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:5.7
        volumes:
          - todo-mysql-data:/var/lib/mysql
    
    volumes:
      todo-mysql-data:
    
  11. 指定環境變數。

    version: "3.7"
    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:5.7
        volumes:
          - todo-mysql-data:/var/lib/mysql
        environment: 
          MYSQL_ROOT_PASSWORD: <your-password>
          MYSQL_DATABASE: todos
    
    volumes:
      todo-mysql-data:
    

此時,完整的 docker-compose.yml 看起來會像這樣:

version: "3.7"

services:
  app:
    image: node:20-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: <your-password>
      MYSQL_DB: todos

  mysql:
    image: mysql:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment: 
      MYSQL_ROOT_PASSWORD: <your-password>
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

執行應用程式堆疊

現在您已擁有 docker-compose.yml 檔案,請試試看。

  1. 請確定應用程式和資料庫沒有其他複本正在執行。 在 Docker 流程執行中,以滑鼠右鍵按一下任何執行中的容器,然後選取 [移除]。 或者,在命令列中,使用 docker rm 命令,如先前的範例中所示。

  2. 在 VS Code 總管中,以滑鼠右鍵按一下 docker-compose.yml,然後選取 [向上撰寫]。 或者,在命令列使用這個 docker 命令。

    docker-compose up -d
    

    -d 參數會使命令在背景中執行。

    您應該會看到類似下列結果的輸出。

    [+] Building 0.0s (0/0)
    [+] Running 2/2
    ✔ Container app-app-1    Started                                                                                                       0.9s 
    ✔ Container app-mysql-1  Running
    

    已建立磁碟區以及網路。 根據預設,Docker Compose 會特別為應用程式堆疊建立網路。

  3. 在 Docker 延伸模組中,以滑鼠右鍵按一下應用程式容器,然後選取 [檢視記錄]。 若要從命令列檢視記錄,請使用 docker logs 命令。

    mysql_1  | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
    mysql_1  | Version: '5.7.27'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
    app_1    | Connected to mysql db at host mysql
    app_1    | Listening on port 3000
    

    每個服務的記錄會交錯成單一串流。 透過此行為,您可以監看時間相關問題。

    服務名稱會顯示在行開頭,以協助區分訊息。 若要檢視特定服務的記錄,請將服務名稱新增至 logs 命令的結尾。

  4. 此時,您應該能夠開啟應用程式。 輸入您的 http://localhost:3000 瀏覽器。

使用完這些容器時,只要移除這些容器即可。

  • 在 VS Code 總管中,以滑鼠右鍵按一下 docker-compose.yml,然後選取 [向下撰寫]
  • 請在命令列執行 docker-compose down

容器隨即停止。 網路已移除。

根據預設,不會移除撰寫檔案中的具名磁碟區。 如果您要移除磁碟區,請執行 docker-compose down --volumes

清除資源

您在本教學課程系列中使用的必要條件可用於未來的 Docker 開發。 沒有任何理由刪除或解除安裝任何項目。

下一步

在本教學課程中,您已了解多容器應用程式和 Docker Compose。 Docker Compose 可大幅簡化多重服務應用程式的定義和共用。

以下是一些對您有用的資源: