

使用.NET 6开发TodoList应用(30)——实现Docker打包和部署
source link: https://www.cnblogs.com/code4nothing/p/build-todolist-30.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

系列导航及源代码#
需求#
.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。
参考资料#
Recommend
-
61
首先在这里给大家拜个晚年,祝大家新年愉快,编程功力节节高升~~ 我自己有制定年度规划的习惯,之前也一直在用OneNote在做。OneNote虽然好用,可是没有相关统计功能。这样就不容易把握计划制定的是否合理。于是就趁着放假,顺手做一个简单的ToDoList小程
-
35
开始 安装react脚手架并初始化项目 {代码...} 此时项目已经运行在 :localhost:3000 安装 electron electron 7.0.0 实在太坑爹了 使用6.1.2没有问题。 {代码...} 新建main.js {代码...} 启动项目 在package.json文件中添加: {代码...} 然后执行: {代码...} 看到...
-
14
使用 PyInstaller 打包 Python Web应用,实现免安装一键启动 2020/5/25 0 人评论 9,710 次阅读 ...
-
4
需求# 在我们项目开发的过程中,使用.NET 6自带的日志系统有时是不能满足实际需求的,比如有的时候我们需要将日志输出到第三方平台上,最典型的应用...
-
9
需求# 上一篇文章中我们完成了数据存储服务的接入,从这一篇开始将正...
-
6
系列导航及源代码#
-
2
系列导航及源代码#
-
7
文章正文: 前面的四个章节我们主要讲解了MongoDB的相关基础知识,接下来我们就开始进入使用.NET7操作MongoDB开发一个ToDoList系统实战教程。本章节主要介绍的是如何快熟搭建一个简单明了的后端项目框架。 MongoDB从入门到实战的相关教程...
-
4
文章正文: Swagger是什么? Swagger是一个规范且完整API文档管理框架,可以用于生成、描述和调用可视化的RESTful风格的 Web 服务。Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无须访问源码、文...
-
3
文章正文: 前几章教程我们把ToDoList系统的基本框架搭建好了,现在我们需要根据我们的需求把ToDoList系统所需要的系统集合(相当于关系型数据库中的数据库表)。接下来我们先简单概述一下这个系统主要需要实现的功能以及实现这些功能我们需要设...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK