ASP.NET Core & Docker 實戰經驗分享

必讀

本文總結了博主在使用持續集成 ASP.NET Core & Docker & Jenkins 的經驗,裏面有些章節講的是 Docker Compose,這是因爲早期版本的Visual Studio 2017添加的Docker支持採用的Docker Compose方式,15.8 版本之後,就放棄了Docker Compose方式,直接採用Dockerfile,簡單、方面。好比第二小節中出現的 docker-compose.override.yml 這個就是之前版本的VS2017自動生成的Docker Compose 文件,特此說明。持續集成教程連接:《ASP.NET Core & Docker 零基礎持續集成html

一.前言

最近一直在研究和實踐ASP.NET Core、Docker、持續集成。在ASP.NET Core 和 Dcoker結合下遇到了一些坑,在此記錄和分享,但願對你們有一些幫助。git

二.中間鏡像

多階段構建產生的中間鏡像,鏡像緩存層等github

我前面寫過一個 《ASP.NET Core & Docker 零基礎持續集成 》的教程。裏面咱們經過持續集成工具Jenkins構建Docker鏡像並運行容器,採用的是Docker Compose來進行編排構建運行的(Visual Studio 2017添加Docker支持是採用的Docker Compose)。細心的朋友可能會發現,每次構建完畢之後經過docker images命令查詢,能夠發現多了許多沒有名稱(<none>)的鏡像。這些都是構建過程當中的中間鏡像,咱們能夠在構建完成之後 進行統一刪除。docker

刪除全部無名稱鏡像:shell

docker rmi $(docker images -f "dangling=true" -q)

此命令應當加在構建的最後一步,示例:windows

echo ---------------Remove-Orphans------------------
docker-compose -f src/docker-compose.yml -f src/docker-compose.override.yml  -p alipaydemo down --rmi local --remove-orphans
echo ---------------Publishing...------------------
docker-compose -f "src/docker-compose.yml" -f "src/docker-compose.override.yml"  -p alipaydemo up -d --build

echo ---------------Clear-Images...------------------
docker rmi $(docker images -f "dangling=true" -q)

執行以後會看到如下效果:緩存

1526621696765

這是很是有必要的,由於若是每次構建都殘留一些中間鏡像,會額外消耗咱們的磁盤空間的。服務器

三.固定容器外部端口 (Docker Compose)

這裏主要講的是在自動化構建的過程當中,經過docker compose來運行容器的外部端口,而不是直接經過docker run命令來指定。app

咱們經過Visual Studio 2017添加Docker支持(Docker Compose),經過Docker Compose編排構建運行容器,咱們會發現每次構建之後,運行的容器的外部端口都不是固定的,好比3277四、3277五、32776等等。這對於咱們設置了Nginx反向代理和API Gateway等配置的確定是十分不方便的,咱們每次構建完畢之後還要去改這些配置,不是扯淡嗎。因此咱們須要固定咱們容器運行的外部端口,咱們能夠經過改變docker compose的yml文件來固定容器的外部端口。less

Visual Studio 2017 添加的Docker支持所生成的文件有以下結構:

1526669282843

我是用的版本爲VS2017 15.6.5。若是是更早的版本添加Docker支持可能會多出一個docker-compose.ci.build.yml文件,其實這一步不必,目前的最新的VS2017已經移除了該文件。

咱們固定容器外部端口須要修改的是docker-compose.override.yml文件,咱們須要修改的是ports。默認爲:

ports:
  - "80"

這個80端口只是容器的內部端口,咱們進行以下修改來知道容器運行時映射到服務器的端口也就是外部端口:

ports:
  - "32775:80"

經過上面的設置,咱們將容器的外部端口指定爲32775,這樣咱們在構建完成之後,容器運行之後的外部端口都將會爲32775,無需再次修改Nginx反向代理等配置。

四.設置鏡像版本 (Docker Compose)

咱們的應用程序具備不一樣的版本號,咱們不一樣版本的應用程序構建出來的鏡像應該也是具備不一樣的版本的,咱們能夠經過設置鏡像的Tag來表示不一樣的版本:

1526669778555

咱們一樣能夠在docker compose的yml裏面進行設置,此次修改的是docker-compose.yml文件,咱們直接在鏡像的名稱後面設置Tag,語法爲:

image: <鏡像名稱>:<Tag>

好比我設置一個名爲alipaydemo的鏡像Tag爲V1:

image: alipaydemo:v1

完整的配置分享:

version: '3'

services:
  alipay.demo.pcpayment:
    image: alipaydemopcpayment:v1
    container_name: alipaydemocontainer
    build:
      context: .
      dockerfile: Alipay.Demo.PCPayment/Dockerfile

五.設置容器名稱 (Docker Compose)

咱們在經過docker compose運行的容器將會被指定一個默認的容器名稱,若是是第四節的配置,那麼容器的默認名稱爲alipaydemopcpayment.alipay.demo.pcpayment.build_1,具備很是一長串,此時咱們能夠本身來指定這個容器的名稱,一樣咱們須要修改docker-compose.yml文件,設置容器名稱的命令格式爲:

container_name: <容器名稱>

完整的配置分享:

version: '3'

services:
  alipay.demo.pcpayment:
    image: alipaydemopcpayment:v1
    container_name: alipaydemocontainer
    build:
      context: .
      dockerfile: Alipay.Demo.PCPayment/Dockerfile

經過上面的配置咱們將容器名稱設置爲了alipaydemocontainer

1526670495716

六.設置容器重啓策略 (Docker Compose)

某一天我對服務器進行了重啓,重啓之後發現經過Docker運行的服務沒法訪問了,而後查看緣由,發現Docker服務沒有開機自啓,啓動了Docker之後發現容器又沒有自動啓動。

1.設置Docker開機自啓

咱們能夠直接經過chkconfig命令來設置Docker開啓自啓:

chkconfig docker

執行成功以下:

1526673472666

2.設置容器隨Docker啓動

咱們要讓容器隨Docker啓動,就必須設置容器的重啓策略爲always,咱們經過docker compose來運行容器時能夠在yml裏面指定。打開docker-compose.override.yml文件,添加配置:

restart: always

完整的配置示例:

version: '3'

services:
  alipay.demo.pcpayment:
    restart: always
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
    ports:
      - "32775:80"

七.Docker的重啓策略

1.設置容器重啓策略

這裏講的設置容器重啓策略主要是經過命令來進行交互,並不是第六節講的經過docker compose來設置重啓策略,是對第六節的一個擴展閱讀。

咱們能夠在使用docker run命令時經過--restart參數來設置重啓策略:

docker run -d --restart=always alipaydemo
docker run -d --restart=on-failure:10 alipaydemo

第一條命令表明容器退出時老是重啓容器,第二條表明在容器非正常退出時重啓容器,最多重啓10次。

對於已經運行的容器能夠經過docker update命令來指定:

docker update --restart=always alipaydemo

2.Docker容器的重啓策略

Docker容器的重啓策略是面向生產環境的一個啓動策略,在開發過程當中能夠忽略該策略。 Docker容器的重啓都是由Docker守護進程完成的,所以與守護進程息息相關。 Docker容器的重啓策略以下:

  • no,默認策略,在容器退出時不重啓容器
  • on-failure,在容器非正常退出時(退出狀態非0),纔會重啓容器
    • on-failure:3,在容器非正常退出時重啓容器,最多重啓3次
  • always,在容器退出時老是重啓容器
  • unless-stopped,在容器退出時老是重啓容器,可是不考慮在Docker守護進程啓動時就已經中止了的容器

3.Docker容器的退出狀態碼

docker run的退出狀態碼以下:

  • 0,表示正常退出

  • 非0,表示異常退出(退出狀態碼採用chroot標準)

    • 125,Docker守護進程自己的錯誤
    • 126,容器啓動後,要執行的默認命令沒法調用
    • 127,容器啓動後,要執行的默認命令不存在
  • 其餘命令狀態碼,容器啓動後正常執行命令,退出命令時該命令的返回狀態碼做爲容器的退出狀態碼

參考資料:http://www.javashuo.com/article/p-uktveoum-ek.html

八.設置自動交互

咱們在編寫Dockerfile時,能夠經過RUN命令來運行一些命令,由此咱們能夠經過運行apt-get等命令,將一些必要的組件安裝到咱們的鏡像之中,好比lsof等。咱們有以下配置:

RUN apt-get install lsof

可是咱們在安裝一個組件時,很是有可能遇到交互操做,好比「Dou you want to xxx?[y/n]」等,遇到這種將會中斷咱們的Docker鏡像構建過程,那麼如何解決呢?咱們能夠給命令指定--assume-yes來實現自動交互:

RUN apt-get install lsof --assume-yes

持續集成自動化構建過程當中,如若不設置自動交互將會被中斷:

1526672437061

使用apt-get install命令之前,最好使用apt-get update更新一下,避免出現問題。

九.ASP.NET Core 生成圖片問題

你們應該知道目前.NET Core(2.0)仍是沒有System.Drawing程序集,若是咱們要使用Image等對象來完成生成圖片驗證碼、圖片二維碼等操做只有經過第三方編寫的組件,ZKWeb.System.Drawing即是其中一個,咱們使用它之後,咱們在windows上運行良好,無需其餘額外的操做。可是咱們一到Linux運行或者使用Docker(dotnet鏡像使用的是ubantu環境)運行時,會發現程序沒法正常生成圖片,會出現異常,這是由於咱們的zk在Linux/Docker下運行須要安裝一個名爲 libgdiplus 的組件,咱們在構建Docker鏡像的時候能夠經過RUN命令使用apt-get命令進行安裝:

RUN apt-get update
RUN apt-get install libgdiplus --assume-yes
RUN cd /usr/lib
RUN ln -s libgdiplus.so gdiplus.dll

apt-get update是很是有必要的

完整的Dockerfile配置提供給你們參考:

FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY Alipay.Demo.PCPayment.sln ./
COPY Alipay.Demo.PCPayment/Alipay.Demo.PCPayment.csproj Alipay.Demo.PCPayment/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/Alipay.Demo.PCPayment
RUN dotnet build -c Release -o /app

FROM build AS publish
RUN dotnet publish -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
RUN apt-get update
RUN apt-get install libgdiplus --assume-yes
RUN cd /usr/lib
RUN ln -s libgdiplus.so gdiplus.dll
ENTRYPOINT ["dotnet", "Alipay.Demo.PCPayment.dll"]

十.寫在最後

本文乃是我在實踐ASP.NET Core & Docker & 持續集成過程當中遇到的問題和解決之道,完徹底全的實戰經驗、總結,但願能幫助到你們。關於實踐ASP.NET Core & Docker 構建持續集成你們能夠看個人這一系列文章:《ASP.NET Core & Docker 零基礎持續集成》。本文所說的實戰是我在實踐個人開源項目:

https://github.com/dotnetcore/Alipay.AopSdk.Core

此項目及其演示項目經過持續集成自動化發佈到Nuget和經過Docker運行。這個項目是一個支持.NET Core的支付寶的服務端SDK項目,不只僅提供支付能力,還提供支付寶生活號、服務窗、行業合做等開發。以爲好的但願能給一個Star支持(手動滑稽)。

最後分享給你們一個高效寫博客的方法,本文亦是用此來進行編寫和發佈:http://www.cnblogs.com/stulzq/p/9043632.html

相關文章
相關標籤/搜索