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文件来固定容器的外部端口。asp.net

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

相关文章
相关标签/搜索