ASP.NET Core 3.0 : 二十八. 在Docker中的部署以及docker-compose的使用
本文简要说一下asp.net core 在docker中部署以及docker-compose的使用 (asp.net core 系列目录)。 系统环境为centos 8 。
先打个广告:求职中,求坑,求推荐
一、概述
简单说一下docker的几个概念:
记得上学的时候流行一种安装操作系统的方式,叫ghost,大概是这样的:
进入pe系统打开ghost软件,点击“local”,然后选择“partition”,最后选择“from image”,选择一个.gho后缀文件,就开始系统安装了。
安装好系统之后,根据自己的需求又安装了一些常用软件,然后为了避免下次重装系统还要安装这些,可以将现在状态的系统再次用ghost备份一下,生成一个.gho后缀的镜像文件,这个镜像又可以用来安装系统。
一个.gho文件可以用来为多台电脑安装系统,每个被安装好的系统又可以被备份成一个.gho文件文件。
而类比docker,有这样几个概念:
- image(镜像):有点像.gho后缀的镜像文件。
- container(容器):就像用.gho安装成功的一个操作系统。
- repository(仓库):存放镜像的仓库,像git一样可以有公有的仓库也可以有私有的。微软的仓库地址为:
但实际上docker不是一个操作系统,也不像一个虚拟机一样,它是要共享宿主的内核的。
而且一般建议一个容器只跑一个进程,不像操作系统那样可以多进程运行。(虽然也可以通过一些方法在一个docker容器中跑多个应用,但不建议这样做。)
二、安装docker
说明:安装centos 8 选择了最小安装,此处就不说了,下面说一下docker的安装过程。
- 安装一些必要的系统工具:
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
- 添加软件源信息:
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 更新 yum 缓存:
sudo yum makecache fast
- 安装 docker-ce:
sudo yum -y install docker-ce
- 启动 docker 后台服务
sudo systemctl start docker
注意:安装docker-ce的时候可能报错:package docker-ce …… requires containerd.io >= 1.2.2-3, but none of the providers can be installed
是因为containerd.io版本过低,可去下面网站查看新版本:
https://download.docker.com/linux/centos/7/x86_64/edge/packages
- 下载:
wget https://download.docker.com/linux/centos/7/x86_64/edge/packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm
- 安装:
yum -y install containerd.io-1.2.6-3.3.el7.x86_64.rpm
再次执行sudo yum -y install docker-ce安装即可。
三、docker的几个常见命令
- 搜索远程存储库中的镜像,例如mongodb的镜像
docker search mongo
- 拉取仓库中的镜像
docker pull mongo
- 列出本地镜像。
docker images
可以看到本地镜像中包了mongo镜像。
- 运行镜像生成一个容器
docker run --name mongotodocker -p 27088:27017 -d mongo
含义: 用镜像mongo运行生成一个容器,名字为mongotodocker ,将容器内的端口27017映射到主机的27088端口。-p 指的是端口映射。 -d是说后台运行容器,并返回容器id;
- 列出所有容器。
docker ps -a
可以看到刚运行起来的容器。
- 停止容器
docker stop mongotodocker
- 删除容器。
docker rm mongotodocker
- 删除镜像
docker rmi mongo
具体每个命令都有一些参数可用,这里只是简单介绍一下使用方法。具体的文档网上很多,不一一说明了。
四、注册docker账号
注册一个账号(可选项),地址: ,可以在上面建自己的仓库。
五、创建一个asp.net core 项目,生成并运行docker镜像
新建一个名为dockercomposedemo的api项目,直接发布,拷贝发布的文件到centos系统中,例如/home/aspcore目录。并在该目录新建一个文本文件名为dockerfile,内容如下:
from mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim as base workdir /app expose 80 copy . . entrypoint ["dotnet", "dockercomposedemo.dll"]
含义是:引用包含3.0运行时的镜像,这个镜像在远程仓库中,若本地没有提前pull下来,会先执行pull操作获取到本地。然后将工作目录设为/app , 拷贝发布的项目文件,设置进程的入口是通过dotnet运行dockercomposedemo.dll。
执行如下命令:
cd /home/aspcore docker build -t dockertest .
注意第二行后后面有个'.'不能少。 含义就是按照dockerfile文件中设置的规则生成名为dockertest的镜像。
此时执行docker images命令可以看到本地镜像中已经有了 mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim 和 dockertest 两个镜像。
运行这个镜像生成容器:
docker run --name aspdocker -p 8080:80 -d dockertest
生成一个名为aspdocker 的容器,并将容器的80端口映射到主机的8080端口。访问项目默认提供的controller:http://192.168.183.230:8080/weatherforecast
可以看到能正常访问。
六:使用docker-compose
因为一个docker容器只建议运行一个应用,那么一个项目就可能会存在多个容器被运行,可能包含多个项目、数据库等,这时候就需要对这些容器进行统一的管理,从构建运行开始到运行后状态的监控等。
这时候有个简易的方法就是docker-compose,它可以完成多个docker的统一管理,包括docker镜像构建、容器运行、相关配置以及docker之间的依赖关系等。
下面举个简单例子,这个dockercomposedemo项目需要搭配一个mongodb数据库,这样除了该项目外还需要一个docker容器运行mongodb数据库。
这时候用docker-compose就方便多了。docker-compose的核心是docker-compose.yml文件,看一下对应这个例子的文件内容:
version: '3.4' services: demomvc: image: thisdemoimage build: context: . dockerfile: dockerfile environment: - aspnetcore_dbconn=mongodb://192.168.183.230:27089 - aspnetcore_dbname=dockerdb ports: - "5103:80" depends_on: - mongodocker mongodocker: image: mongo ports: - "27089:27017"
在services节点下定义了demomvc和mongodocker两个服务,一个是asp.net core的项目,一个是mongodb数据库。
每个节点下的image参数指定了采用的镜像名称,ports指定端口映射。此处的mongodb设置未涉及持久化,实际使用时要注意设置。
asp.net core的项目的thisdemoimage镜像是不存在的,下面指定了build方法。当然也可以先创建好镜像然后在这里使用就像mongo服务的设置一样。
depends_on表示本服务对另一个服务的依赖,本例中就是asp.net core项目依赖mongodb项目。
environment用于设置环境变量,作用是什么呢?
有一些设置,比如本例中的数据库连接,如果将连接字符串写在了项目中的appsettings.json中,而这个文件被“固化”到镜像中了,是不能修改的,除非重新生成镜像,非常麻烦。
所以可以通过这样的环境变量在外面设置。
将项目引用nuget包mongodb.driver, 修改weatherforecastcontroller的get方法:
[httpget] public ienumerable<weatherforecast> get() { var rng = new random(); _mongohelper.insertone(new weatherforecast { date = datetime.now.adddays(1), temperaturec = rng.next(-20, 55), summary = summaries[rng.next(summaries.length)] }); return _mongohelper.findlist<weatherforecast>(); }
每次都是先插入一条,然后返回所有记录。这里简要的写了一个mongohelper:
public class mongohelper { private readonly imongodatabase database; public mongohelper(iconfiguration configuration) : this(configuration["aspnetcore_dbconn"], configuration.getsection("aspnetcore_dbname").value) { } public mongohelper(string connectionstring,string dbname) { mongoclient mongoclient = new mongoclient(connectionstring); database = mongoclient.getdatabase(dbname); } public list<t> findlist<t>(filterdefinition<t> filter = null, string collectionname = null) { collectionname ??= typeof(t).name; filter ??= new bsondocument(); var collection = database.getcollection<t>(collectionname); return collection.find(filter).tolist(); } public void insertone<t>(t model, string collectionname = null) { collectionname ??= typeof(t).name; var collection = database.getcollection<t>(collectionname); collection.insertone(model); } }
连接字符串采用 iconfiguration中的设置。
这里有个不算技巧的技巧,为了方便在非docker的情况下测试,依然可以在appsettings.json文件中设置mongodb的连接字符串,当部署到docker中的时候,通过docker环境变量配置的连接字符串会覆盖appsettings.json中的配置。
这是因为在讲述iconfiguration的文章中说过,系统是先加载appsettings.json中的设置,后加载环境变量中的设置的,二者的key相同,所以最终会以环境变量中的配置为准。
重新发布项目并将文件拷贝到/home/aspcore目录,其中的dockerfile文件不变,添加本例中的docker-compose.yml文件。
docker-compose是需要单独下载安装的, 执行命令:
sudo curl -l "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
如果提示权限错误,需执行如下命令:
sudo chmod +x /usr/local/bin/docker-compose
安装好之后执行 docker-compose --version 验证是否安装成功。
都准备好了,执行如下命令:
cd /home/aspcore docker-compose up
执行成功后访问 http://192.168.183.230:5103/weatherforecast 进行测试。
七、windows下开发
我们都知道,visualstudio经常“贴心”的帮我们做好多事,例如git的图形化操作。对于docker也是如此。
若要在windows环境下开发及调试docker,可按下面步骤完成。
首先需下载并安装docker desktop
页面上有个图标:,点击下载。安装后右下角会有 图标,右键可以做一些设置。
它支持windows和linux两种主机
通过docker version 命令可以看出当前主机类型。也可以右键点击右下角的图标,有个switch to ……的选项,可以知道当前主机类型,点击后切换到另一种类型。
命令切换:c:\program files\docker\docker\dockercli.exe -switchdaemon
解决方案启用docker支持:
新建项目的时候,勾选启用docker支持:
已有项目可以右键点击项目,添加docker支持:
两种方式都会要求选择主机类型是windows还是linux。
此时visual studio帮我们会在项目中添加一个名为dockerfile的文件:
from mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim as base workdir /app expose 80 from mcr.microsoft.com/dotnet/core/sdk:3.0-buster as build workdir /src copy ["dockerdemo/dockerdemo.csproj", "dockerdemo/"] run dotnet restore "dockerdemo/dockerdemo.csproj" copy . . workdir "/src/dockerdemo" run dotnet build "dockerdemo.csproj" -c release -o /app/build from build as publish run dotnet publish "dockerdemo.csproj" -c release -o /app/publish from base as final workdir /app copy --from=publish /app/publish . entrypoint ["dotnet", "dockerdemo.dll"]
这个文件和上面例子中我们自己创建的优点不同,它包含了4个from,第一个和最后一个和我们自己创建的有点像,只是visual studio帮我们自动添加了sdk镜像的拉取、项目的编译、项目发布的过程。
这里用到了两个镜像,第一个from调用了微软官方的包含asp.net core 3.0 的运行时版镜像。第二个from用到了包含.net core 3.0的sdk的镜像,因为我们需要对项目进行生成和发布操作。
通过添加docker的支持,可以使用visual studio开发并将项目自动发布到docker进行调试。但选择系统环境为windows的时候速度很快,选择linux的时候由于网络问题非常慢。网上有临时的解决方案。
如果多个项目想采用docker-compose管理,在上面添加docker支持的图中可以看到有一个“容器业务流程协调程序支持”, 添加它就会自动生成一个docker-compose.yml文件。
docker-compose主要用于当前主机中的docker的管理,对于多主机的集群管理,就需要docker swarm或者kubernetes了。