1. 程式人生 > >ASP.NET Core & Docker 實戰經驗分享

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

一.前言

最近一直在研究和實踐ASP.NET Core、Docker、持續整合。在ASP.NET Core 和 Dcoker結合下遇到了一些坑,在此記錄和分享,希望對大家有一些幫助。

二.中間映象

多階段構建產生的中間映象,映象快取層等

我前面寫過一個 《ASP.NET Core & Docker 零基礎持續整合 》的教程。裡面我們通過持續整合工具Jenkins構建Docker映象並執行容器,採用的是Docker Compose來進行編排構建執行的(Visual Studio 2017新增Docker支援是採用的Docker Compose)。細心的朋友可能會發現,每次構建完畢以後通過docker images

命令查詢,可以發現多了許多沒有名稱(<none>)的映象。這些都是構建過程中的中間映象,我們可以在構建完成以後 進行統一刪除。

刪除所有無名稱映象:

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

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

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 run命令來指定。

我們通過Visual Studio 2017新增Docker支援(Docker Compose),通過Docker Compose編排構建執行容器,我們會發現每次構建以後,執行的容器的外部埠都不是固定的,比如32774、32775、32776等等。這對於我們設定了Nginx反向代理和API Gateway等配置的肯定是十分不方便的,我們每次構建完畢以後還要去改這些配置,不是扯淡嗎。所以我們需要固定我們容器執行的外部埠,我們可以通過改變docker compose的yml檔案來固定容器的外部埠。

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反向代理等配置。

四.設定映象版本

我們的應用程式具有不同的版本號,我們不同版本的應用程式構建出來的映象應該也是具有不同的版本的,我們可以通過設定映象的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執行的容器將會被指定一個預設的容器名稱,如果是第四節的配置,那麼容器的預設名稱為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執行的服務無法訪問了,然後檢視原因,發現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,容器啟動後,要執行的預設命令不存在
  • 其他命令狀態碼,容器啟動後正常執行命令,退出命令時該命令的返回狀態碼作為容器的退出狀態碼

八.設定自動互動

我們在編寫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 零基礎持續整合》。本文所說的實戰是我在實踐我的開源專案:

此專案及其演示專案通過持續整合自動化釋出到Nuget和通過Docker執行。這個專案是一個支援.NET Core的支付寶的服務端SDK專案,不僅僅提供支付能力,還提供支付寶生活號、服務窗、行業合作等開發。覺得好的希望能給一個Star支援(手動滑稽)。

相關推薦

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

一.前言 最近一直在研究和實踐ASP.NET Core、Docker、持續整合。在ASP.NET Core 和 Dcoker結合下遇到了一些坑,在此記錄和分享,希望對大家有一些幫助。 二.中間映象 多階段構建產生的中間映象,映象快取層等 我前面寫過一個 《ASP.NET Core & Docker

【無私分享ASP.NET CORE 專案實戰(第九章)】建立區域Areas,新增TagHelper

目錄索引 簡介   在Asp.net Core VS2015中,我們發現還有很多不太簡便的地方,比如右擊新增檢視,轉到試圖頁等功能圖不見了,雖然我們可以通過工具欄的自定義命令,把這兩個右擊選單新增上,但是貌似是灰色的不能用。   其實,這樣也好,通過手動建立,更讓我們深刻的理解M

【無私分享ASP.NET CORE 專案實戰(第二章)】新增EF上下文物件,新增介面、實現類以及無處不在的依賴注入(DI)

目錄索引 簡介   上一章,我們介紹了安裝和新建控制器、檢視,這一章我們來建立個數據模型,並且新增介面和實現類。 新增EF上下文物件   按照我們以前的習慣,我們還是新建幾個資料夾   Commons:存放幫助類   Domians:資料模型   Services

【無私分享ASP.NET CORE 專案實戰(第十章)】釋出專案到 Linux 上執行 Core 專案

目錄索引 簡介   ASP.Net Core 給我們帶來的最大的亮點就是跨平臺,我在我電腦(win7)上用虛擬機器建了個 CentOS7 ,來演示下,我們windows上的專案如何釋出專案到Linux上執行。我這裡有個在windows上搭建過的程式,我們主要演示如何在linux上執

【無私分享ASP.NET CORE 專案實戰(第六章)】讀取配置檔案(一) appsettings.json

目錄索引 簡介   在我們之前的Asp.net mvc 開發中,一提到配置檔案,我們不由的想到 web.config 和 app.config,在 core 中,我們看到了很多的變化,新的配置系統顯得更加輕量級,具有更好的擴充套件性,並且支援多樣化的資料來源。   部落格園對於這個的

【無私分享ASP.NET CORE 專案實戰(第八章)】讀取配置檔案(二) 讀取自定義配置檔案

目錄索引 簡介   但隨之產生了問題:我們使用的是在 Startup.cs 中(如下圖)來實現配置讀取,有兩個問題 ① 我們如果定義N種配置,是否要再這裡新增N條這樣的配置 ; ② 如果我們的配置不想寫在appsettings.json中呢     解決問題

【無私分享ASP.NET CORE 專案實戰(第十三章)】Asp.net Core 使用MyCat分散式資料庫,實現讀寫分離

目錄索引 簡介   MyCat2.0版本很快就釋出了,關於MyCat的動態和一些問題,大家可以加一下MyCat的官方QQ群:106088787。我們今天主要介紹一下,在我們的Asp.net Core中如何使用Mycat,這源於一個大神(Amamiya Yuuko)的分享,但是,這中

【無私分享ASP.NET CORE 專案實戰(第十一章)】Asp.net Core 快取 MemoryCache 和 Redis

1 /// <summary> 2 /// 修改快取 3 /// </summary> 4 /// <param name="key">快取Key</param> 5 ///

【無私分享ASP.NET CORE 專案實戰(第四章)】Code First 建立資料庫和資料表

目錄索引 簡介   本章我們來介紹下Asp.net Core 使用 CodeFirst 建立資料庫和表,通過 控制檯 和 dotnet ef 兩種方式 修改EF上下文物件,新增測試類   我修改了一下名字,Domains 改為了 wkmvc.Data   我們新建一個

【無私分享ASP.NET CORE 專案實戰(第十二章)】新增對SqlServer、MySql、Oracle的支援

目錄索引 簡介   增加對多資料庫的支援,並不是意味著同時對多種資料庫操作,當然,後面,我們會嘗試同時對多種資料庫操作,這可能需要多個上下文,暫且不論。分散式資料庫,我們採用的是阿里雲的Mycat,這個後面會更新出來。我們今天的場景是:我們的專案可能是在windows上開發的使用的

【無私分享ASP.NET CORE 專案實戰(第七章)】檔案操作 FileHelper

目錄索引 簡介   在程式設計中,我們很多情況下,會用到對檔案的操作,在 上一個系列 中,我們有很多檔案基本操作的示例,在Core中有一些改變,主要是我們常用的Server.MapPath()不存在了,不知道後續的版本會不會有,在這裡,我們只能自己封裝方法去實現。今天,我們就對一些基本

【無私分享ASP.NET CORE 專案實戰(第五章)】Repository倉儲 UnitofWork

1 public abstract class Repository<T> : IRepository<T> where T : class 2 { 3 #region 資料上下文 4 5 /// <s

【無私分享ASP.NET CORE 專案實戰(第十四章)】圖形驗證碼的實現

1 public class VierificationCodeServices 2 { 3 /// <summary> 4 /// 該方法用於生成指定位數的隨機數 5 /// </summary> 6

【無私分享ASP.NET CORE 專案實戰(第三章)】EntityFramework下領域驅動設計的應用

這好像就是比我的多了一個“中轉層”,把我們的介面作為了一箇中轉,領域層繼承了倉儲實現業務和資料操作,這有什麼實際意義嗎?希望大家指正一下: 我不理解的是,如果是按照這樣,那麼我如果要修改註冊方法,比如我要在上面方法中傳遞 eamil,name,password 的基礎上還需要傳遞手機號碼,那麼我需要修改

Asp.net Core 入門實戰 2.請求流程

圖片 入門 可能 其他 http請求 交流 stop 擴展 del Asp.Net Core 是開源,跨平臺,模塊化,快速而簡單的Web框架. Asp.net Core官網的一個源碼合集,方便一次性Clone,喜歡的(Star),本系列持續更新,也可以通過我的網站訪問,歡迎

ASP.NET Core + Docker +Jenkins 實現持續集成

before hash net stuck 超時時間 ref shell 腳本 conf cut 1.新建一個ASP.NET Core MVC應用程序: 2.將其上傳到git: 3.建立Jenkins任務 (1)選擇“新建任務”,輸入任務名稱,選擇“自由風格項目”,然後

Asp.net core 專案實戰 新聞網站+後臺 原始碼、設計原理 、視訊教程

首先說明,視訊教程、原始碼並非本人原創 本人將專案分割開,並寫了一些說明。 該視訊教程 地址  https://study.163.com/course/courseMain.htm?courseId=1005955006 原作者 筆者正在學 ASP.NET Core ,發現這

使用ML.NET + ASP.NET Core + Docker + Azure Container Instances部署.NET機器學習模型

cat ports sed tar enc convert esp asp truct 本文將使用ML.NET創建機器學習分類模型,通過ASP.NET Core Web API公開它,將其打包到Docker容器中,並通過Azure Container Instances將其

ASP.NET Core 專案實戰(持續更新~~~)

 一、前言   準備寫這個系列文章的設想開始於今年9月,毫無意外,期間又又又又拖了很長時間,文章主要是為了記錄自己學習使用 ASP.NET Core Web API 與 Vue 建立一個前後端分離的專案的整個過程。嗯,2018年快要結束了,應該能在 .NET Core 3.0 正式版和 Vue 3

Getting Started With ASP.NET Core & Docker

Containers — Docker: IntroductionNow, let’s move on to a brief explanation on what are the main purposes of using containers in software development.What i