使用.NET 6开发TodoList应用(30)——实现Docker打包和部署
系列导航及源代码
需求
.NET 6 Web API应用使用最多的场景是作为后端微服务应用,在实际的项目中,我们一般都是通过将应用程序打包成docker镜像进行发布,以便更好地进行部署,包括基于Kubernetes平台的微服务项目部署。
一般来说作为微服务部署的应用程序,都是位于某个虚拟子网下的,也就是说它们不直接暴露给外部用户,请求都是走的内部网络,所以很少会有HTTPS的需求,但是作为演示,在本文中我们还是会介绍如何实现HTTPS访问docker中的应用程序。
目标
实现应用程序的docker镜像打包运行,包括实现基于HTTPS的访问。
原理与思路
应用程序docker镜像打包的实现思路很简单,准备一个正确的dockerfile,再根据需要进行HTTPS配置,最后正确构建镜像就可以了。
实现
实现Docker镜像打包
在Api
项目中新建dockerfile文件,一般我们构建应用程序都是通过两步构建:第一步进行编译发布,第二步将发布的文件拷贝到运行时环境中,这样可以减少镜像的大小。
如果你是使用Visual Studio或者Rider开发项目,可以在创建项目的时候就将是否使用Docker支持
选上,选择容器环境为Linux即可,项目模版会为我们自动生成正确的Dockerfile。或者我们也可以在项目上右击,选择添加Docker支持
。
下面是我们手写的dockerfile的文件内容,对于编写dockerfile经验不多的小伙伴来说,最容易出错的地方就是路径的问题。因为我们将dockefile文件生成在了Api
项目中了,所以单从文件内容里的路径来看,是有问题的,但是不要紧,我们在打包镜像的时候可以指定dockefile文件执行的上下文,只要在解决方案目录下执行docker build就没问题了。
ARG NET_IMAGE=6.0-bullseye-slim
FROM mcr.microsoft.com/dotnet/aspnet:${NET_IMAGE} AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
ENV ASPNETCORE_ENVIRONMENT=Development
FROM mcr.microsoft.com/dotnet/sdk:${NET_IMAGE} AS build
WORKDIR /src
COPY ["src/TodoList.Api/TodoList.Api.csproj", "TodoList.Api/"]
COPY ["src/TodoList.Application/TodoList.Application.csproj", "TodoList.Application/"]
COPY ["src/TodoList.Domain/TodoList.Domain.csproj", "TodoList.Domain/"]
COPY ["src/TodoList.Infrastructure/TodoList.Infrastructure.csproj", "TodoList.Infrastructure/"]
RUN dotnet restore "TodoList.Api/TodoList.Api.csproj"
COPY ./src .
WORKDIR "/src/TodoList.Api"
RUN dotnet build "TodoList.Api.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish --no-restore "TodoList.Api.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "TodoList.Api.dll"]
在构建镜像之前,有几个小坑需要注意一下:
- 暂时删除
Program
中的UseHttpsRedirection
中间件,因为我们还没有配置HTTPS证书; - 在
Api
项目的csproj文件中,将TodoList.Api.xml
文件在Debug模式下的配置复制到Release中,否则会报错Could not find file '/app/TodoList.Api.xml
; - 修改对应appsettings.{env}.json中的数据库连接字符串,使用docker网络模型获取其他容器的方式,将localhost改为mssql,这个名字是在本地运行sql server docker的容器名称,我们将使用docker网络允许应用程序连接到数据库docker容器。
下面我们就来构建一下这个镜像,确保位于解决方案目录下,注意最后那.
指明了当前选择的dockerfile文件执行的上下文路径,即解决方案目录:
$ docker build -t todo-list -f src/TodoList.Api/Dockerfile .
生成的镜像:
运行起来,把80端口暴露出来,使用--link
参数指出需要将当前应用容器连接到数据库容器所在的网络,并使用API客户端去验证登陆请求:
$ docker run -p 80:80 --name=todo_list_in_docker --link=mssql -d todo-list
4733f35c2c9558b78e3c7b9281536d8891f19bf87b18fa0ad953e94f7b984184
请求认证:
实现HTTPS访问
接下来我们为容器添加HTTPS支持,为了实现这一点,我们当然还是需要继续使用UseHttpsRedirection
中间件,然后需要添加一个证书,并在启动容器的时候添加这个证书。
dotnet dev-certs https -ep ${HOME}/.aspnet/https/aspnetapp.pfx -p Test@Password
dotnet dev-certs https --trust
重新build并运行容器,这次我们使用HTTPS的5001端口去访问容器中的API,需要将HTTPS容器内的443端口暴露到host上的端口(我选择的是5001端口)并制定相关的HTTPS的环境变量,证书的指定并将host上保存证书的路径挂载到容器内可以访问到。
docker run \
-p 80:80 \
-p 5001:443 \
--name=todo_list_in_docker \
--link=mssql \
-e ASPNETCORE_URLS="https://+;http://+" \
-e ASPNETCORE_HTTPS_PORT=5001 \
-e ASPNETCORE_Kestrel__Certificates__Default__Password="Test@Password" \
-e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx \
-v ${HOME}/.aspnet/https:/https/ \
-d \
todo-list
增加docker-compose功能
到这里我们发现了一个比较麻烦的地方在于我们需要记住这些配置,并且每次需要手动分别启动数据库容器和应用容器,我们完全可以通过docker-compose来完成,所以我们先把应用容器和数据库容器都停止并删除掉,开始在解决方案目录下新建docker-compose文件:
version: '3.4'
services:
todo-list:
image: todo-list
# 配置端口转发
ports:
- "80:80"
- "5001:443"
# 配置容器环境变量
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+;http://+
- ASPNETCORE_HTTPS_PORT=5001
- ASPNETCORE_Kestrel__Certificates__Default__Password=Test@Password
- ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
# 挂载证书路径
volumes:
- ~/.aspnet/https:/https:ro
# 需要先启动数据库容器
depends_on:
- mssql
# todo-list通过public网络响应请求,通过private网络连接数据库容器
networks:
- private
- public
mssql:
image: mcr.microsoft.com/mssql/server:2019-latest
# 配置端口转发,这是为从主机直接访问数据库需要的,如果没有从主机直接访问数据库的需求,只需要声明容器端口1433不做转发即可
ports:
- "1433:1433"
environment:
- SA_PASSWORD=StrongPwd123
- ACCEPT_EULA=Y
# 挂载数据目录实现持久化
volumes:
- mssqldata:/var/opt/mssql
networks:
- private
- public
# 因为mssqldata路径之前已经创建了,所以需要在这里声明使用已有的
volumes:
mssqldata:
networks:
private:
public:
运行起来以后继续请求认证:
$ docker-compose up --build
Creating network "todolist_private" with the default driver
Creating network "todolist_public" with the default driver
Recreating todolist_mssql_1 ... done
Recreating todolist_todo-list_1 ... done
Attaching to todolist_mssql_1, todolist_todo-list_1
// 省略后面的日志....
请求结果:
到此为止如何使用容器去进行应用程序打包和部署的演示就结束了,关于如何在Kubernetes和CI/CD中应用这些步骤,会在后面将微服务的系列中再次涉及到。
总结
docker打包应用程序比较容易出错的地方在于dockerfile路径,除此之外如果在容器中还需要有其他操作比如安装一些第三方的agent(比如splunk agent),也需要仔细操作,关于如何进行Docker Build的Debug,可以参考其他人写的文章,例如这篇:Debugging Docker builds。
参考资料
- Hosting ASP.NET Core images with Docker over HTTPS
- Hosting ASP.NET Core images with Docker Compose over HTTPS
- Debugging Docker builds
使用.NET 6开发TodoList应用(30)——实现Docker打包和部署的更多相关文章
- 使用.NET 6开发TodoList应用(3)——引入第三方日志库
需求 在我们项目开发的过程中,使用.NET 6自带的日志系统有时是不能满足实际需求的,比如有的时候我们需要将日志输出到第三方平台上,最典型的应用就是在各种云平台上,为了集中管理日志和查询日志,通常会选 ...
- 使用.NET 6开发TodoList应用(1)——系列背景
前言 想到要写这样一个系列博客,初衷有两个:一是希望通过一个实践项目,将.NET 6 WebAPI开发的基础知识串联起来,帮助那些想要入门.NET 6服务端开发的朋友们快速上手,对使用.NET 6开发 ...
- 使用.NET 6开发TodoList应用(2)——项目结构搭建
为了不影响阅读的体验,我把系列导航放到文章最后了,有需要的小伙伴可以直接通过导航跳转到对应的文章 : P TodoList需求简介 首先明确一下我们即将开发的这个TodoList应用都需要完成什么功能 ...
- 使用.NET 6开发TodoList应用(4)——引入数据存储
需求 作为后端CRUD程序员(bushi,数据存储是开发后端服务一个非常重要的组件.对我们的TodoList项目来说,自然也需要配置数据存储.目前的需求很简单: 需要能持久化TodoList对象并对其 ...
- 使用.NET 6开发TodoList应用(5)——领域实体创建
需求 上一篇文章中我们完成了数据存储服务的接入,从这一篇开始将正式进入业务逻辑部分的开发. 首先要定义和解决的问题是,根据TodoList项目的需求,我们应该设计怎样的数据实体,如何去进行操作? 长文 ...
- 使用.NET 6开发TodoList应用(5.1)——实现Repository模式
需求 经常写CRUD程序的小伙伴们可能都经历过定义很多Repository接口,分别做对应的实现,依赖注入并使用的场景.有的时候会发现,很多分散的XXXXRepository的逻辑都是基本一致的,于是 ...
- 使用.NET 6开发TodoList应用(6)——使用MediatR实现POST请求
需求 需求很简单:如何创建新的TodoList和TodoItem并持久化. 初学者按照教程去实现的话,应该分成以下几步:创建Controller并实现POST方法:实用传入的请求参数new一个数据库实 ...
- 使用.NET 6开发TodoList应用文章索引
系列导航 使用.NET 6开发TodoList应用(1)--系列背景 使用.NET 6开发TodoList应用(2)--项目结构搭建 使用.NET 6开发TodoList应用(3)--引入第三方日志 ...
- 使用.NET 6开发TodoList应用(24)——实现基于JWT的Identity功能
系列导航及源代码 使用.NET 6开发TodoList应用文章索引 需求 在.NET Web API开发中还有一个很重要的需求是关于身份认证和授权的,这个主题非常大,所以本文不打算面面俱到地介绍整个主 ...
随机推荐
- 替DateDif哭诉一把(Excel函数集团)
Excel中有个工作表函数DateDif,专门用来计算两日期之间的日差.月差.年差,传说十分好用. 具体用法在此就省略了,好奇的童鞋请自行*度~ 可是,在Excel里,他却是个"没户口&qu ...
- 日期与时间函数(Excel函数集团)
此处文章均为本妖原创,供下载.学习.探讨! 文章下载源是Office365国内版1Driver,如有链接问题请联系我. 请勿用于商业!谢谢 下载地址:https://officecommunity-m ...
- springboot项目WEB-INF 目录 jsp页面报404
我是跟着<深入浅出 Spring Boot 2.x>这本书学习的,在"初识Spring MVC"章节中,搭建项目,然后访问jsp页面时报错:Path with &quo ...
- iNeuOS工业互联网操作系统,发布3.6.4版本:云端安全控制和实时日志功能,附Chrome、Firefox和Edge浏览器测试性能对比
目 录 1. 概述... 2 2. 平台演示... 2 3. 云端控制和实时日志设计和技术... 2 4. 实时日志测试... 2 1. 概述 ...
- 误入 GitHub 游戏区,意外地收获颇丰
这天中午,我和往常一样就着美食视频吃完午饭,然后起身泡了一杯"高沫". 我闻着茶香享受着午后的阳光,慵懒地坐在工位上习惯性的打开 GitHub 游荡,酝酿着睡意. 误打误撞,我来到 ...
- 大学MOOC课程视频下载、流文件合并、批量重命名、b站视频下载及学习课程视频推荐
计算机行业技术更新快,编程语言种类多,在当今大数据和人工智能的时代,为了能在相关领域有所成就,就必须掌握好python.R等语言,较好的数学基础和深入的行业背景知识.计算机从业人员务必践行" ...
- 【Tools】VS搭建Qt开发环境
00. 目录 @ 目录 00. 目录 01. 概述 02. Visual Studio 2019安装 03. Qt6安装 04. qt-vsaddin插件下载 05. qt-vsaddin插件安装 0 ...
- c/c++实现CRC查表及算法
说明 CRC被广泛应用到各个领域.足见其厉害之处 本文介绍的是CRC查表法. 拷贝代码即可使用 CRC 的起始值 本来默认是0, 实际生产中遇到过,CRC初始值为0xFFFF, 故将其初始值以参数的形 ...
- fmt的API介绍(版本: 7.0.1)
!!版权声明:本文为博主原创文章,版权归原文作者和博客园共有,谢绝任何形式的 转载!! 作者:mohist 本文翻译: https://fmt.dev/latest/api.html 水平有限,仅供参 ...
- 【LeetCode】1135. Connecting Cities With Minimum Cost 解题报告 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 Kruskal算法 日期 题目地址:https://l ...