1. 程式人生 > >.Net Core微服務入門全紀錄(八)——Docker Compose與容器網路

.Net Core微服務入門全紀錄(八)——Docker Compose與容器網路

Tips:本篇已加入系列文章閱讀目錄,可點選檢視更多相關文章。 # 前言 上一篇【[.Net Core微服務入門全紀錄(七)——IdentityServer4-授權認證](https://www.cnblogs.com/xhznl/p/13132260.html)】中使用IdentityServer4完成了鑑權中心的搭建,配合閘道器實現了統一的授權認證。進行到這裡,系統環境已經比較複雜了,想把整個系統執行起來會非常繁瑣:要執行Consul、業務服務、閘道器、鑑權中心、web客戶端,還要安裝資料庫、MQ等等。。。那麼本篇將使用Docker Compose來解決以上問題,僅需一個簡單的命令,即可啟動整個環境。 # Docker Compose 什麼是Docker Compose? > Compose 是用於定義和執行多容器 Docker 應用程式的工具。通過 Compose,您可以使用 YML 檔案來配置應用程式需要的所有服務。然後,使用一個命令,就可以從 YML 檔案配置中建立並啟動所有服務。 簡單來理解,Compose類似一個批量工具,可以執行一組命令,支援批量構建映象,批量啟動容器,批量刪除容器等等功能。 Windows的Docker Desktop中已經包括了Compose,Linux下Compose則需要單獨安裝一下。 # yml file yml檔案是使用Compose必不可少的,在編寫yml檔案之前還需要準備Dockerfile。 之前的章節中,有些服務不是在Docker中執行的,現在全部放到Docker中。確保解決方案中每個專案都新增Docker支援。 ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708143653146.png) 在根目錄新建docker-compose.yml檔案: ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708144446816.png) 以下是docker-compose.yml檔案內容: ```yaml version: '3.4' #Compose檔案版本 services: #服務 auth: #定義"auth"服務 對應的是鑑權中心專案 build: #構建 context: . #構建上下文(目錄) dockerfile: ./IDS4.AuthCenter/Dockerfile #Dockerfile檔案目錄 ports: #埠 - '9080:9080' #容器外部9080 容器內部9080 environment: #環境變數 - ASPNETCORE_URLS=http://+:9080 #程式在容器內部http://+:9080執行 也可以寫成http://0.0.0.0:9080 networks: #容器網路 - my-net #自定義網路my-net web: #定義"web"服務 對應的web客戶端專案 build: context: . dockerfile: ./Web.MVC/Dockerfile ports: - '5000:5000' environment: - ASPNETCORE_URLS=http://+:5000 networks: - my-net depends_on: #"web"服務依賴於"auth"服務和"apigateway"服務,此服務會在依賴服務之後執行 - auth - apigateway apigateway: #定義"apigateway"服務 對應的閘道器專案 build: context: . dockerfile: ./Ocelot.APIGateway/Dockerfile ports: - '9070:9070' environment: - ASPNETCORE_URLS=http://+:9070 networks: - my-net depends_on: - orderapi1 - orderapi2 - orderapi3 - productapi1 - productapi2 - productapi3 productapi1: #定義"productapi1"服務 對應的產品服務專案 image: productapi #指定映象名稱,如果不指定 預設是:netcoremicroservicedemo_productapi1,因為下面要用到所以指定一下 build: context: . dockerfile: ./Product.API/Dockerfile ports: - '9050:9050' environment: - ASPNETCORE_URLS=http://+:9050 - ConsulSetting:ServiceIP=productapi1 #程式引數 - ConsulSetting:ServicePort=9050 #程式引數 networks: - my-net depends_on: - consul - postgres - rabbitmq productapi2: image: productapi #指定映象名稱為productapi,productapi1服務中已經構建了productapi映象,所以不用重複構建 ports: - '9051:9051' environment: - ASPNETCORE_URLS=http://+:9051 - ConsulSetting:ServiceIP=productapi2 - ConsulSetting:ServicePort=9051 networks: - my-net depends_on: - productapi1 productapi3: image: productapi ports: - '9052:9052' environment: - ASPNETCORE_URLS=http://+:9052 - ConsulSetting:ServiceIP=productapi3 - ConsulSetting:ServicePort=9052 networks: - my-net depends_on: - productapi1 orderapi1: image: orderapi build: context: . dockerfile: ./Order.API/Dockerfile ports: - '9060:9060' environment: - ASPNETCORE_URLS=http://+:9060 - ConsulSetting:ServiceIP=orderapi1 - ConsulSetting:ServicePort=9060 networks: - my-net depends_on: - consul - postgres - rabbitmq orderapi2: image: orderapi ports: - '9061:9061' environment: - ASPNETCORE_URLS=http://+:9061 - ConsulSetting:ServiceIP=orderapi2 - ConsulSetting:ServicePort=9061 networks: - my-net depends_on: - orderapi1 orderapi3: image: orderapi ports: - '9062:9062' environment: - ASPNETCORE_URLS=http://+:9062 - ConsulSetting:ServiceIP=orderapi3 - ConsulSetting:ServicePort=9062 networks: - my-net depends_on: - orderapi1 consul: image: consul #指定映象名稱為consul,本地如果沒有consul映象,會從docker遠端倉庫拉取 ports: - '8500:8500' networks: - my-net postgres: image: postgres environment: POSTGRES_PASSWORD: pg123456 networks: - my-net rabbitmq: image: rabbitmq networks: - my-net networks: #定義容器網路 my-net: #my-net網路 driver: bridge #網路模式為bridge ``` 以上yml檔案定義了auth,web,apigateway,productapi1,productapi2,productapi3,orderapi1,orderapi2,orderapi3,consul,postgres,rabbitmq 12個服務(容器),和一個容器網路 my-net。這裡的productapi和orderapi相當於是基於同樣的映象各運行了3個容器,這其實不太合理,正常他們應該分佈在多個docker中。。。 檔案的內容雖然有點多,但是應該不難理解,上面的關鍵字我都有註釋。下面再簡單介紹一下檔案中的networks容器網路。 ## 容器網路 前面的章節中有提到過,預設情況下容器之間的通訊是比較麻煩的,之前是通過`host.docker.internal`或者容器的IP去訪問,雖然是可以訪問但有些不友好。更好的方式是,我們可以自定義一個bridge網路,將所有服務(容器)加入這個網路中,那麼容器之間就可以直接通過服務名稱通訊了。bridge模式只是docker網路模式中的一種,有興趣的話可以自行搜尋一下。 # 程式碼修改 既然程式都執行在docker中,那就不能寫`localhost`,`host.docker.internal`之類的主機名了,統一改為docker-compose.yml檔案中定義的服務名。如下: ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708160904491.png) ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708160954383.png) ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708161058460.png) 還有多處修改就不全貼出來了,都是些類似的改動。這些配置還是不要寫在程式碼裡,改動起來比較亂。 這裡有一個特殊的就是identityserver4鑑權服務,這個服務是容器內外部都需要訪問的(容器內部ids4發現文件等介面的呼叫,外部瀏覽器訪問),所以不能直接寫服務名auth,寫auth的話外部無法訪問,寫localhost的話內部又無法訪問。最後是參考eShopOnContainers專案,使用`docker.for.win.localhost`來滿足內外部的訪問需求: ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708162415826.png) ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708162457521.png) 理論上用`host.docker.internal`或許也可以,沒去測試。。。這個配置放到Compose的環境變數裡會比較好,這裡只是為了方便。 eShopOnContainers專案是微軟官方出品的開源專案,對於學習微服務,docker等技術非常有幫助。 專案地址:https://github.com/dotnet-architecture/eShopOnContainers # 構建與啟動 完成以上操作後,進入專案根目錄執行`docker-compose build` ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708164734777.png) build完成後,執行`docker-compose up -d`,-d代表在後臺執行 ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708170620719.png) (第一次up,orderapi2,orderapi3,productapi2,productapi3這4個服務會起不來,是因為他們啟動時有建立資料庫的操作,同時啟動會導致後起來的4個重複的服務建立資料庫時報錯,因為orderapi1和productapi1在建立同樣的資料庫。。。這個前面說過的。這裡等up完再執行一次up就好了) 瀏覽器訪問:http://localhost:5000/ ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708165542301.png) 登入後: ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/GIF%202020-7-8%2017-13-34.gif) 這樣執行系統是不是非常簡單呢?想要摧毀這個環境也很簡單,只需要一句`docker-compose down` ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708170339444.png) 如果不習慣docker命令,推薦使用vscode,裝一下docker外掛,很方便。 ![](https://gitee.com/xhznl/Blog.Images/raw/master/images/image-20200708185653285.png) # 總結 上文用到了Docker-Compose的3個命令: 構建:`docker-compose build` 啟動:`docker-compose up` 銷燬:`docker-compose down` 其實build命令也可以省略,執行up時如果沒有build的話會自動build,無論多複雜的系統環境,只需要一個`docker-compose up`命令即可啟動。不過映象需要重新bulid的時候,還是要用到build命令。Compose還有一些其他命令,需要的話可以自行搜尋。 主要的工作量在於docker-compose.yml檔案的編寫。 需要程式碼的點這裡:https://github.com/xiajingren/NetCoreMicroserv