Docker可以说是现在微服务,DevOps的基础,咱们.Net Core自然也得上Docker。.Net Core发布到Docker容器的教程网上也有不少,但是今天还是想来写一写。

你搜.Net core程序发布到Docker网上一般常见的有两种方案:

  • 1、在本地编译成Dll文件后通过SCP命令或者WinSCP等工具上传到服务器上,然后构建Docker镜像再运行容器。该方案跟传统的发布很像,麻烦的地方是每次都要打开相关工具往服务器上复制文件。
  • 2、在服务端直接通过Git获取最新源代码后编译成Dll然后构建Docker镜像再运行容器。该方案免去了往服务器复制文件这步操作,但是服务器环境需要安装.Net Core SDK 来编译源代码。

    自从用了Docker简直懒的不能自理,我既不想手工复制文件到服务器,也不想在服务器装.Net Core环境。显然只要Docker镜像包含.Net Core SDK环境就可以在Docker内帮我们编译代码然后运行,这样连我们的服务器都不用装啥.Net Core的环境拉。

在Docker内编译发布.Net Core程序并运行

新建一个Asp.net Core MVC项目

我们使用一个Asp.net Core MVC程序来演示如何发布到Docker并运行。



使用vs新建一个Asp.net core mvc项目

  public class HomeController : Controller
{
public IActionResult Index()
{
return Content($"Core for docker , {DateTime.Now} , verson 2");
}
}

修改HomeController下的index Action,直接输出一段文字

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel(op =>
{
op.ListenAnyIP(5000);
})
.UseStartup<Startup>();

修改Program下的CreateWebHostBuilder方法,让Kestrel监听5000端口



本地运行一下试试

推送源码到代码仓库

把我们的代码推送到对应的Git仓库,方便我们从部署服务器上直接拉取最新的代码。

X:\workspace\CoreForDocker>git remote add origin https://gitee.com/kklldog/CoreForDocker.git

X:\workspace\CoreForDocker>git push -u origin master
Username for 'https://gitee.com': xxx@gmail.com
Password for 'https://xxx@gmail.com@gitee.com':
Counting objects: 88, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (83/83), done.
Writing objects: 100% (88/88), 527.07 KiB | 2.43 MiB/s, done.
Total 88 (delta 7), reused 0 (delta 0)
remote: Powered By Gitee.com
To https://gitee.com/kklldog/CoreForDocker.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

添加Dockerfile文件

在CoreForDocker下新增一个Dockerfile文件,注意没有任何扩展名。我们需要基于microsoft/dotnet:latest这个镜像构建一个新的镜像。并且在构建的过程中直接对源码进行编译并发布。

FROM microsoft/dotnet:latest
WORKDIR /app
COPY /. /app
RUN dotnet restore
RUN dotnet publish -o /out -c Release
EXPOSE 5000
ENTRYPOINT ["dotnet", "/out/CoreForDocker.dll"]

大概解释下Dockerfile的意思:

FROM microsoft/dotnet:latest:使用dotnet的最新镜像,这个镜像其实对应的应该就是2.2-sdk这个镜像,里面包含了dotnet-core 2.2 sdk

WORKDIR /app:指定工作目录为app

COPY /. /app复制宿主机当前目录的内容到容器的app文件夹

RUN dotnet restore:还原nuget包

RUN dotnet publish -o /out -c Release编译并发布程序集到容器的out目录

EXPOSE 5000:暴露5000端口

ENTRYPOINT ["dotnet", "/out/CoreForDocker.dll"]:容器启动的时候执行dotnet命令,参数为/out/CoreForDocker.dll



Dockerfile的文件属性设置为始终复制

新建好Dockerfile后git push到代码仓库。

在服务器上构建Docker镜像

这里以Ubuntu为例,ssh登录到服务器后使用git clone命令拉取源代码。

git clone https://gitee.com/kklldog/CoreForDocker.git

进入源码目录

cd CodeForDocker\CodeForDocker

使用docker build命令构建新的镜像,注意不要忘记最后一个'.'

docker build -t image_code4docker .

运行容器

如果以上步骤都没有报错,那么恭喜你镜像已经构建成功了,我们可以使用此镜像运行Docker容器了。

docker run -d --name code4docker -p 5000:5000 -v /ect/localtime:/ect/localtime image_core4docker

使用image_core4docker镜像运行一个名为core4docker的容器,绑定宿主机的5000到容器的5000口。其中需要注意的是-v参数映射宿主机的/ect/localtime文件夹到容器的/ect/localtime文件夹,因为经过实践发现容器中的时区有可能跟宿主机不一致,需要映射宿主机的/ect/localtime让容器的时区跟宿主机保持一致。



访问一下服务器的5000端口,发现能够正确返回数据表示我们的Asp.net Core程序在容器中运行成功了

以后当我们对源码进行修改,并提交后,我们只需在服务器上拉取最新的代码然后使用docker build,docker run命令来再次生成镜像并运行容器。但是手工输入docker build,docker run的命令好像也很麻烦,参数又那么多,太烦了。

使用shell脚本简化操作

为了偷懒不想敲那么长的命令,我们可以构建一个脚本,把命令一次性写好,以后只要运行一次脚本就可以了。

使用vim新建一个publish.sh的文件

vim publish.sh

键盘上按i进入编辑模式,输入以下内容

cd CoreForDocker/CoreForDocker
git pull
docker stop core4docker
docker rm core4docker
docker rmi image_core4docker
docker build -t image_core4docker .
docker run --name core4docker -d -p 5000:5000 -v /etc/localtime:/etc/localtime image_core4docker

以上命令,不光有新建镜像跟运行容器的命令,还有移除原来的容器跟镜像的命令

按ecs进入命令模式,退出保存

:wq

让我们模拟修改一下源代码,并提交到代码仓库

    public IActionResult Index()
{
return Content($"Core for docker , {DateTime.Now} , version 2");
}

再次修改homecontroller的index action,输出内容上新增一个version

ssh登录到服务器,运行publish.sh文件

/bin/bash publish.sh



跑完之后我们再次访问下服务器的5000口,数据返回正确,表示服务器上跑的已经是最新的程序了

总结

通过以上演示我们基本了解如何通过git跟docker配合在Ubuntu服务器上不安装.Net Core SDK来发布.Net Core 程序到容器中运行,并且通过shell脚本的方式再次简化发布。但是尽管这样每次发布都需要ssh到服务器上然后运行脚本,特别是开发环境可能经常需要发布,还是觉得麻烦。有没有什么办法让我们push代码后服务器自动就开始部署最新的代码的到容器中运行了呢?

后面我会介绍下如何通过jenkins跟webhook来做CICD。

.Net Core in Docker - 在容器内编译发布并运行的更多相关文章

  1. ASP.NET Core使用Docker进行容器化托管和部署

    一.课程介绍 人生苦短,我用.NET Core!今天给大家分享一下Asp.Net Core以Docker进行容器化部署托管,本课程并不是完完全全的零基础Docker入门教学,课程知识点难免有没覆盖全面 ...

  2. Asp.Net Core 使用Docker进行容器化部署(一)

    前几篇文章介绍了Liunx下的环境搭建,今天来分享一下.Net Core在Liunx上的部署. 我采用的方案是使用Dokcer作为运行虚拟机,Nginx作为Http服务器来进行反向代理,你可以理解为D ...

  3. Docker从容器内拷贝文件到主机上

    //以elasticsearch容器为例 //运行es docker run -d -p 9200:9200 elasticsearch:5.4 //查看已运行的容器 docker ps //进去容器 ...

  4. 深入理解Spring的容器内事件发布监听机制

    目录 1. 什么是事件监听机制 2. JDK中对事件监听机制的支持 2.1 基于JDK实现对任务执行结果的监听 3.Spring容器对事件监听机制的支持 3.1 基于Spring实现对任务执行结果的监 ...

  5. Asp.Net Core 使用Docker进行容器化部署(二)使用Nginx进行反向代理

    上一篇介绍了Asp.Net 程序在Docker中的部署,这篇介绍使用Nginx对Docker的实例进行反向代理 一.修改Nginx配置文件 使用winscp链接Liunx服务器,在/ect/nginx ...

  6. Docker 修改容器内的时区

    利用docker发布服务,发现 程序用获取的系统时间比正常时间晚了8个小时 进入容器 docker exec -it /bin/sh 查询时间 date -R 发现时区为0时区 解决思路 1.复制相应 ...

  7. Docker - 解决容器内获取的时间和主机的时间不一样的问题

    问题背景 分别在容器和主机下执行 date 命令 可以看到,时间是完全不一样的 解决方案 在运行容器时,挂载 /etc/localtime  目录 docker run -d -v /etc/loca ...

  8. .net core 在 Docker 上的部署

    Docker可以说是现在微服务,DevOps的基础,咱们.Net Core自然也得上Docker..Net Core发布到Docker容器的教程网上也有不少,但是今天还是想来写一写.你搜.Net co ...

  9. asp.net core结合docker实现自动化获取源码、部署、更新

    之前入坑dotnet core,由于一开始就遇到在windows上编译发布的web无法直接放到centos上执行.之后便直接研究docker,实现在容器中编译发布.然后就越玩越大,后来利用git的ho ...

随机推荐

  1. Windows phone 自定义用户控件(UserControl)——ColorPicker

    编码前 学习Windows phone自定义用户控件,在<WPF编程宝典>学习的小例子.并根据windows phone稍微的不同,做了点修改.ColorPicker(颜色拾取器):拥有三 ...

  2. 前端基础之Bootstrap

    1. 页面加载完之后才执行的JS代码        1. DOM方式            window.onload = function(){}        2. jQuery方式       ...

  3. 91. Decode Ways (Array; DP)

    A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...

  4. Django基础教程

    实例练习1-提交数据并展示 1.app_01下的views.py info_list=[] def userInfor(req): if req.method=="POST": u ...

  5. FutureTask详解

    1 基本概念 1.1 Callable与Future Runnable封装一个异步运行的任务,可以把它想象成为一个没有参数和返回值的异步方法.Callable与Runnable类似,但是有返回值.Ca ...

  6. BZOJ1106[POI2007]立方体大作战tet - 树状数组

    描述 一个叫做立方体大作战的游戏风靡整个Byteotia.这个游戏的规则是相当复杂的,所以我们只介绍他的简单规则:给定玩家一个有2n个元素的栈,元素一个叠一个地放置.这些元素拥有n个不同的编号,每个编 ...

  7. break MISSING_BLOCK_LABEL_160; 看源代码出现的,源代码是反编译的

    break MISSING_BLOCK_LABEL_160; FileNotFoundException fnfe; fnfe; out.close(); throw fnfe; in.close() ...

  8. Java中的内存划分

    Java程序在运行时,需要在内存中分配空间.为了提高运行效率,就对数据进行了不同的空间划分.因为每一片区域都有特定的数据处理方式和内存管理方式. 具体分为5种内存空间: 程序计数器:保证线程切换后能恢 ...

  9. 2018.10.09 NOIP模拟 路途(递推+矩阵快速幂优化)

    传送门 签到题.(考试的时候写挂爆0) 令AiA_iAi​表示邻接矩阵的iii次幂. 于是就是求Al+Al+1+...+ArA_l+A_{l+1}+...+A_rAl​+Al+1​+...+Ar​. ...

  10. Part 5 - Django ORM(17-20)

    https://github.com/sibtc/django-beginners-guide/tree/v0.5-lw from django.conf.urls import url from d ...