本文简要说一下 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 账号
注册一个账号(可选项), 地址: https://hub.docker.com/ , 可以在上面建自己的仓库.
五, 创建一个 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 的核心是 compose.YAML 文件, 看一下对应这个例子的文件内容:
- 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 指定端口映射.
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.YAML 文件.
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 http://192.168.183.230:8080/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.YAML 文件.
Docker-Compose 主要用于当前主机中的 docker 的管理, 对于多主机的集群管理, 就需要 Docker Swarm 或者 Kubernetes 了.
来源: https://www.cnblogs.com/FlyLolo/p/ASPNETCore_28.html