把AspDotNetCoreMvc程序運行在Docker上-part5:使用docker-compose


在上一part把AspDotNetCoreMvc程序運行在Docker上-part4:實現負載均衡》中,我們通過幾個比較復雜的步驟在docker平台上實現了對網站程序的負載均衡,配置步驟比較多。如果實際的站點較少,整個架構比較簡單的情況下,這么做沒有太大問題,如果應用較多的時候,會容易出錯。那么這時候我們可能會想到自己寫一些腳本來實現自動化,當然這是可行的。然而docker已為我們着想好,給我們提供了docker-compose功能,利用它我們可以實現對復雜應用的管理,包括容器、網絡、volume等。

 

准備工作

先刪除上一part我們創建的容器、網絡和volume(不用覺得可惜,后面用上docker-compose可以輕易實現)

docker rm -f $(docker ps -aq)
docker network rm $(docker network ls -q)
docker volume rm $(docker volume ls -q)

 

安裝docker-compose

在linux平台上需要手動執行如下命令安裝

sudo curl -L https://github.com/docker/compose/releases/download/1.17.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

(最新版本可以從這里https://github.com/docker/compose/releases獲知)

安裝之后,運行docker-compose –version檢查是否成功

 

准備MVC站點程序

可以從這里下載

https://github.com/shenba2014/AspDotNetCoreMvcDocker/tree/docker-compose

然后執行

dotnet restore

bower install

一會用到這個站點程序創建一個鏡像以及對應的容器

 

創建docker-compose配置文件

新建docker-compose.yml文件(在docker所在宿主服務器直接創建也可以)

version: "3"

 

volumes:

   productdata:

 

networks:

   frontend:

   backend:

 

services:

 

   mysql:

      image: "mysql:8.0.0"

   volumes:

      - productdata:/var/lib/mysql

   networks:

      - backend

   environment:

      - MYSQL_ROOT_PASSWORD=password

      - bind-address=0.0.0.0

 

這個文件足夠的自描述,把上一節我們用到的內容都作出了定義,還是簡單解釋一下

version:版本號,目前最新的是3.0

volumes:之前的《把AspDotNetCoreMvc程序運行在Docker上-part3:使用獨立的存儲容器》里面有介紹過,用於在docker容器外存儲數據

networks:在上一part說過,定義了兩個網絡:frontend和backend

services:定義將要用到的容器,這里只定義了mysql容器,這些參數跟使用docker create命令創建容器的參數一致。具體可參考上一part《把AspDotNetCoreMvc程序運行在Docker上-part4:實現負載均衡》。

 

docker-compose執行構建

 

執行如下構建命令

docker-compose –f docker-compose.yml build

輸出結果

WARNING: Some networks were defined but are not used by any service: frontend, backend

mysql uses an image, skipping

這里的警告信息意思是我們定義的兩個網絡還沒被任何服務組件使用。

運行了這個命令只是定義,並沒有真正的創建volume、network或者容器。

 

接下來運行docker-compose.yml定義的應用,才會真正的創建內容

docker-compose -f docker-compose.yml up

可以理解為啟動剛才我們定義的組件,然后會有一堆的輸出內容

WARNING: Some networks were defined but are not used by any service: frontend
Creating network "dockertemp_backend" with the default driver
Creating dockertemp_mysql_1 ...
Creating dockertemp_mysql_1 ... done
Attaching to dockertemp_mysql_1

很明顯docker-compose在依次創建network、容器實例。

名字看起來比較奇怪,都帶了dockertemp_前綴。因為docker-compose.yml所在的目錄命令是dockertemp,所以最終提供的名稱有這個前綴,避免了命名沖突。

而為什么是mysql_1,帶有_1后綴,后續會用到,這里是為了用於橫向擴展做集群的時候用到。

進一步通過如下命令驗證volume、network和容器是創建成功的

docker volume ls

docker netowrk ls

docker ps –a

 

使用docker-compose –f docker-compose.yml down -v可刪除network、容器和volume,全自動完成(保存在volume的數據也會刪除,如果要保留volume把-v去掉即可)。

 

現在docker-compose文件里只定義了一個service,接下來繼續添加MVC站點容器以及負載均衡容器。

 

添加MVC站點容器以及負載均衡容器

首先從以下路徑下載代碼

https://github.com/shenba2014/AspDotNetCoreMvcDocker/tree/docker-compose

這個分支跟之前的不一樣,增加了對支持docker-compose的一些改動。

代碼拉下來之后執行如下命令

dotnet restore

dotnet publish --framework netcoreapp2.0 --configuration Release --output dist

cd dist | npm install

dist文件夾里的內容就是我們后續要用到的MVC站點內容。

 

從源代碼查看完整的docker和docker-compose.yml文件

先看看docker文件的更新內容

 

FROM microsoft/aspnetcore:2.0.0

COPY dist /app

COPY dist/node_modules/wait-for-it.sh/bin/wait-for-it /app/wait-for-it.sh

RUN chmod +x /app/wait-for-it.sh

WORKDIR /app

EXPOSE 80/tcp

ENV WAITHOST=mysql WAITPORT=3306

ENTRYPOINT ./wait-for-it.sh $WAITHOST:$WAITPORT --timeout=0 && exec dotnet AspDotNetCoreMvcDocker.dll

 

紅色部分是新增的內容,這里拷貝了一個wait-for-it的腳本到了容器內部,並且在ENTRYPOINT里設置了等待mysql啟動之后再啟動MVC容器。

 

簡單解釋一下,因為使用了docker-compose啟動容器之后,我們不能確保mysql容器服務是否已正常啟動,如果mysql沒有啟動,那么站點也沒法使用。所以容器必須在mysql容器啟動之后執行,這里就引入了一個npm的package:wait-for-it,這個只能在Linux平台下使用。

 

接下打開完整的docker-compose.yml文件,這里只列出新增的service(完整文件內容不列出,可查看代碼)

dbinit:
     build:
       context: .
       dockerfile: Dockerfile
     networks:
       - backend
     environment:
       - INITDB=true
       - DBHOST=mysql
       - DBPASSWORD=password
     depends_on:
       - mysql
   mvc:
     build:
       context: .
       dockerfile: Dockerfile
     networks:
       - backend
       - frontend
     environment:
       - DBHOST=mysql
       - DBPASSWORD=password
     depends_on:
       - mysql

  loadbalancer:
     image: dockercloud/haproxy
     ports:
       - 3000:80
     links:
       - mvc
     volumes:
       - /var/run/docker.sock:/var/run/docker.sock
     networks:
       - frontend

 

這里才原來的基礎上增加了dbinit,mvc和loadbalancer三個service,分別描述如下

dbinit:主要是用於初始化數據庫,這里是把它當做一個容器來執行,實際在完成了數據庫初始化自后就會退出。

mvc:這里就是MVC站點的容器,跟我們上一part定義MVC的參數類似。主要是增加了depends_on參數,指明mvc容器依賴於mysql容器。

loadbalancer:顧名思義,就是負載均衡服務器容器,通過links參數指向了其代理的站點是MVC容器,並且通過volumes參數配置了/var/run/docker.sock文件映射為主機的文件,具體作用不描述,主要是為了在擴容的時候通知到負載均衡服務器。

 

啟動站點

把上一步的dist文件夾docker、docker-compose.yml文件拷貝到docker服務器(如果開發機就是docker服務器可以忽略),然后在這些文件的所在目錄執行如下命令

docker-compose -f docker-compose.yml build

這個命令之前提到過,類似於編譯,檢查是否有錯誤,實際上不會創建容器

接着運行

docker-compose -f docker-compose.yml up dbinit

開啟dbinit容器,之前我們提到,這個dbinit也是個MVC容器,但是只是負責數據庫初始化,完成之后會自動關閉,這是這個命令的output

Creating network "dockertemp_frontend" with the default driver
Creating network "dockertemp_backend" with the default driver
Creating volume "dockertemp_productdata" with default driver
Creating dockertemp_mysql_1 ...
Creating dockertemp_mysql_1 ... done
Creating dockertemp_dbinit_1 ...
Creating dockertemp_dbinit_1 ... done
Attaching to dockertemp_dbinit_1
dbinit_1        | wait-for-it.sh: waiting for mysql:3306 without a timeout
dbinit_1        | wait-for-it.sh: mysql:3306 is available after 16 seconds
dbinit_1        | warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
dbinit_1        |       No XML encryptor configured. Key {1b1e827d-d1d0-4d0c-a92d-8632ee0791ef} may be persisted to storage in unencrypted form.
dbinit_1        | Preparing Database...
dbinit_1        | Applying Migrations...
dbinit_1        | Creating Seed Data...
dbinit_1        | Database Preparation Complete

dockertemp_dbinit_1 exited with code 0

從output可以看到有一個等待mysql啟動的步驟,等待了16秒。然后是執行了數據庫初始化,創建表以及插入一些種子數據。最后一個行輸出表明該容器自動退出。

 

好了數據庫准備好之后,就可以啟動MVC和負載均衡容器,還是通過docker-compose命令

docker-compose -f docker-compose.yml up mvc loadbalancer

執行完成之后,就可以訪問我們的MVC站點了,這里我們只啟用了一個MVC站點,試試從瀏覽器打開http://192.168.115.136:3000/,一切正常的話就能看到網站和數據了

image

 

做了這么多步驟,就是為了實現負載均衡,接下來一行命令讓他立即擴容到4個MVC站點

docker-compose -f docker-compose.yml scale mvc=4

秒級擴容就是這簡單,不信的話運行docker ps看看下面是不是有4個MVC站點容器,還不相信的話手動多刷幾次http://192.168.115.136:3000/,會發現from server的值是會發生變化的。

image

image

image

image

好了,如果這時候要實現優雅降級怎么辦,沒問題,還是一行命令

docker-compose -f docker-compose.yml scale mvc=1

系統自動移除了三個MVC站點容器,當然也是秒級的。

 

最后關閉所有服務的命令是

docker-compose -f docker-compose.yml stop

 

寫了這么多就是為了描述docker-compose的使用方法,對比上一part,實際上就是把之前的工作都放到一個批處理文件里執行,將所有服務當做一個整體來管理,同時也提供了遍歷站點擴容和降級的方式。看起來已經很方便了,當然還沒完,后續還有大招。

 





 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM