.NET的Dockerfile文件编写要点——以WOL项目为例

本文以 WOL 的.NET 项目为例,介绍了 Dockerfile 的基础知识和编写要点,旨在帮助读者更好地理解和掌握如何为 .NET 应用创建和优化 Dockerfile。

1. 背景

前面我们已经勾选了 Docker 容器化支持,项目已经生成了一个默认的 Dockerfile。但在实际项目中,我们需要根据项目的实际需求和环境来定制化 Dockerfile,以便更好地利用 Docker 的优势。本文将以 WOL (Wake On LAN) 项目为例,详细介绍如何编写一个针对 .NET 应用的 Dockerfile 文件,并分享一些实用的编写技巧。

2. 从默认模板入手

2.1 默认模板

以下是 .NET8 中 Web API 项目的默认模板,在这个默认模板中,我们可以看到一个典型的多阶段构建过程。

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base  
USER app  
WORKDIR /app  
EXPOSE 8080  
EXPOSE 8081  

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build  
ARG BUILD_CONFIGURATION=Release  
WORKDIR /src  
COPY ["WebApplication3/WebApplication3.csproj", "WebApplication3/"]  
RUN dotnet restore "./WebApplication3/./WebApplication3.csproj"  
COPY . .  
WORKDIR "/src/WebApplication3"  
RUN dotnet build "./WebApplication3.csproj" -c $BUILD_CONFIGURATION -o /app/build  

FROM build AS publish  
ARG BUILD_CONFIGURATION=Release  
RUN dotnet publish "./WebApplication3.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false  

FROM base AS final  
WORKDIR /app  
COPY --from=publish /app/publish .  
ENTRYPOINT ["dotnet", "WebApplication3.dll"]

2.2 模板介绍

根据默认模板,我们先来复习一下 Dockerfile 的基本结构:

  1. FROM:指定基础镜像,并可以使用 AS 为这个阶段设置别名,如 FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
  2. USER:设置运行时的用户,如 USER app
  3. WORKDIR:设置工作目录,如 WORKDIR /app
  4. EXPOSE:暴露容器需要监听的端口,如 EXPOSE 8080EXPOSE 8081
  5. COPY:复制文件或目录,如 COPY ["WebApplication3/WebApplication3.csproj", "WebApplication3/"]
  6. RUN:执行命令,如 RUN dotnet restore "./WebApplication3/./WebApplication3.csproj"
  7. ARG:定义构建参数,如 ARG BUILD_CONFIGURATION=Release
  8. ENTRYPOINT:指定容器启动时执行的命令,如 ENTRYPOINT ["dotnet", "WebApplication3.dll"]

在默认模板中,我们还可以看到一个典型的多阶段构建过程。多阶段构建可以减小最终生成的镜像大小,提高构建速度。在上述示例中,我们使用了四个阶段,分别命名为 base、build、publish 和 final,用于不同的构建和运行阶段。

3. WOL 项目的 Dockerfile

一般来说使用默认的 Dockerfile 就可以了,但是有时候我们需要根据项目的特定需求和环境对 Dockerfile 进行调整和优化。

3.1 额外的依赖

项目可能需要一些额外的系统依赖或者工具。可以通过 RUN 指令和包管理器(如 apt-get、yum 等)来安装这些依赖。有时我们可以在编程中就能发现并意识到,但是更多的时候需要我们在容器化后对项目做好测试工作,确保所有功能都能正常运行。

比如在 WOL 项目的工具类中有写这样一个检查设备是否在线的函数:

internal static bool Ping(string iP)
{
    // 检查IP是否在线
    Ping ping = new Ping();
    PingReply pingReply = ping.Send(iP,100);
    return pingReply.Status == IPStatus.Success;
}

写起来倒是很简单,也很省事。但是如果不知道其运行原理的话,就会在容器化后遇到问题。这个函数使用了 System.Net.NetworkInformation.Ping 类来检查目标 IP 地址是否在线,但是其依然是使用了系统的 Ping 工具来处理。Docker 的 Base 镜像都是最简版本,为了轻便,都是不包含 Ping 工具的。

为了解决这个问题,我们就需要将缺失的依赖安装恢复,Debian 的 Ping 工具包为 Iputils-ping,在 final 阶段通过 apt 安装即可。

3.2 更改安装源

在上一节中,我们讨论了安装额外依赖的必要性。为了加速镜像构建过程中的软件包安装,我们可以考虑修改安装源。通常,我们会在物理机上更改镜像源以加速软件包的安装。同样的方法也适用于容器镜像的构建过程。如果不更改安装源,一个镜像的构建可能会花费数小时,这对于开发者来说是难以忍受的。

在使用 mcr.microsoft.com/dotnet/aspnet:8.0 镜像时,底层基于 Debian 系统。为了加速软件包的安装,我们可以更改安装源。在这个例子中,我们将安装源更改为清华大学的镜像源。以下是如何在 Dockerfile 中进行更改的示例:

sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list.d/debian.sources && \
apt-get update

这段代码使用 sed 命令修改了 /etc/apt/sources.list.d/debian.sources 文件中的安装源,将其从 deb.debian.org 更改为了 mirrors.tuna.tsinghua.edu.cn。接下来,使用 apt-get update 命令更新软件包列表。

通过这样的设置,我们可以加速后续软件包的下载和安装过程,从而提高整体镜像构建速度。

3.3 清理垃圾

在执行 apt update 和安装软件包之后,我们需要注意清理系统中产生的缓存和临时文件。这些文件会增加镜像的大小,而在大多数情况下,它们在运行时并不需要。因此,我们可以在 Dockerfile 中添加相应的指令来清理这些垃圾文件,从而减小最终生成的镜像大小。

在使用 apt-get 安装软件包后,可以使用以下命令清理缓存:

apt-get clean
rm -rf /var/lib/apt/lists/*

这段代码首先使用 apt-get clean 命令清理软件包缓存,然后使用 rm -rf /var/lib/apt/lists/* 删除下载的软件包列表。这样一来,我们就可以在构建过程中有效地减小镜像大小。

3.4 权限问题

前面已节我们已经按照了系统的 ping 工具,这样我们就可以正常的使用 System.Net.NetworkInformation.Ping 类来检查目标 IP 地址是否在线。但是在 Linux 系统中,Ping 的实现依赖于 ICMP 协议,而在容器中执行 ICMP 请求通常需要特殊权限,直接容器化运行项目会发现下面的问题:

ping: socktype: SOCK_RAW                                                         
ping: socket: Operation not permitted                                            
ping: => missing cap_net_raw+p capability or setuid?

这是因为为了提高安全性,我们已经将应用的运行用户更改为了 app。为了解决这个问题,我们可以在 Dockerfile 中为更改 ping 命令的权限。

chmod u+s /bin/ping

3.5 编码问题

处理到这里,Dockerfile 的文件就基本解决完毕。但是在实际测试中我们会发现,API 接口中返回的中文会出现乱码的情况:

请添加图片描述

我们可以看到,由配置文件返回的中文信息并没有出现乱码,而通过代码直接返回的中文出现了乱码的情况。这里是因为默认的代码文件编码是 GB18030 ,我们只需要将其改为 UTF-8 ,然后重新制备镜像即可解决这种硬编码导致的乱码问题。

请添加图片描述

4. 要点总结

通过以上的问题重现和处理,我们最终的项目 Dockerfile 如下:

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["WakeOnLan/WakeOnLan.csproj", "WakeOnLan/"]
RUN dotnet restore "WakeOnLan/WakeOnLan.csproj"
COPY . .
WORKDIR "/src/WakeOnLan"
RUN dotnet build "WakeOnLan.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "WakeOnLan.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=true

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list.d/debian.sources \
    && apt-get update \
    && apt-get install -y --no-install-recommends iputils-ping \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* \
    && chmod u+s /bin/ping
WORKDIR /app
USER app
EXPOSE 8080
COPY --from=publish /app/publish .
ENTRYPOINT ["./WakeOnLan"]

最后总结在编写 Dockerfile 时需要注意的一些要点:

  1. 使用多阶段构建:多阶段构建可以减小最终生成的镜像大小,提高构建速度。在上述示例中,我们使用了三个阶段,分别用于编译、发布和运行应用程序。

  2. 使用官方镜像:尽量使用官方提供的基础镜像,以确保镜像的安全性和可靠性。

  3. 优化镜像层:尽量将不会经常变动的文件放在前面,以充分利用镜像层缓存,提高构建速度。

  4. 安装额外依赖:根据项目实际需求,安装额外的依赖和工具,确保所有功能正常运行。

  5. 更改安装源:更改镜像源以加速软件包的下载和安装过程,减少构建时间。

  6. 清理缓存和临时文件:清理缓存和临时文件,减小生成的镜像大小。

  7. 解决权限问题:确保容器化应用程序的安全性,遵循最小权限原则,避免使用 root 用户运行容器。设置运行时用户并调整文件和目录的权限。

  8. 充分测试:对容器化后的项目进行充分的测试工作,以确保所有功能都能正常运行。

通过关注这些要点,我们可以针对实际项目编写和调整 Dockerfile,以便更好地利用 Docker 的优势。同时,对容器化后的项目进行充分的测试工作也是至关重要的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/192325.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

快速上手Banana Pi BPI-R4 MediaTek MT7988A 开源路由器开发板

基础开发 准备开发 * 准备8G以上TF卡、USB转串口线、Ubuntu系统* 使用 USB 串行电缆(3.3V TTL,波特115200)连接到 BPI-R4 上的调试控制台G接地;RXBPI-R4输入;TXBPI-R4输出* BPI-R4 引导程序和设备选择跳线设置* 例子…

部署Jenkins

一、介绍 Jenkins 、Jenkins概念 Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台。这是一个免费的源代码,可以处理任何类型的构建或持续集成。集成Jenkins可以用于一些测试和部署技术。Jenkins是一种软件允…

代码随想录算法训练营第五十天|309. 买卖股票的最佳时机含冷冻期、714. 买卖股票的最佳时机含手续费

LeetCode 309. 买卖股票的最佳时机含冷冻期 题目链接:309. 买卖股票的最佳时机含冷冻期 - 力扣(LeetCode) 所谓的冷冻期,就是卖了股票后的第二天不能买入该股票(股票上的N2,N1是今天卖明天能买),所以影响到…

推荐你一个基于Koin, Ktor Paging等组件的KMM Compose Multiplatform项目

推荐你一个基于Koin, Ktor & Paging等组件的KMM Compose Multiplatform项目 Kotlin Multiplatform Mobile(KMM)已经从一个雄心勃勃的想法发展成为一个稳定而强大的框架,为开发人员提供了在多个平台上无缝共享代码的能力。通过最近的稳定…

肖sir __数据库练习__001

建表语句: create table student ( id int(4),age int(8),sex int(4),name varchar(20), class int(4), math int(4)) DEFAULT charsetutf8; INSERT into student VALUES(1,25,1,‘zhansan’,1833,90); INSERT into student VALUES(2,25,1,‘lisi’,1833,67); INSER…

单片机学习1——点亮一个LED灯

Keil软件编写程序&#xff1a; 特殊功能寄存器声明&#xff1a; #include<reg52.h>sbit LED P1^0;void main() {LED 0;while(1); } 代码说明&#xff1a; sbit 语句是特殊功能位声明。 生成HEX文件&#xff0c;这个文件是下载到单片机里的文件。Options for Target…

三方支付接口成为了电商竞争力的新动力

在当前快速发展的互联网时代&#xff0c;随着电子商务行业的兴起&#xff0c;支付体验已经成为企业获取竞争优势的重要因素。一个快速、安全、便捷的支付环节不仅可以提升用户的体验&#xff0c;还能有效促进交易的完成。在众多支付解决方案中&#xff0c;三方支付接口因其独特…

CMakeList项目构建

CMakeList项目构建 OVERVIEW CMakeList项目构建cmake1.变量定义2.指定源文件路径3.指定头文件路径4.字符串操作5.日志打印6.预定义宏 cmake、makefile都是项目构建工具&#xff0c;通过make命令进行项目构建&#xff0c;大多的IDE都集成了make项目构建&#xff0c;如visual stu…

Java Flight Record 详解

核心概念 Java Flight Record 提供一个低开销的数据收集框架&#xff0c;用于对 Java 应用程序和 HotSpot JVM 进行故障排除。Flight Recorder 记录源自应用程序、JVM和操作系统的事件 Flight Record&#xff0c;顾名思义&#xff0c;相当于飞机黑匣子里保存的飞行记录 事件 …

2023-11-27 LeetCode每日一题(子数组的最小值之和)

2023-11-27每日一题 一、题目编号 907. 子数组的最小值之和二、题目链接 点击跳转到题目位置 三、题目描述 给定一个整数数组 arr&#xff0c;找到 min(b) 的总和&#xff0c;其中 b 的范围为 arr 的每个&#xff08;连续&#xff09;子数组。 由于答案可能很大&#xff…

Shopee买家号想要多开怎么解决?

拥有多个Shopee买家号有很多优势。多账号可以帮助卖家获得更多流量、还能帮助提供关键词排名、提高销量等。 但是要管理多个Shopee买家号并非易事。面对不同账号的登录、注销和切换&#xff0c;可能会花费大量的时间和精力。而且&#xff0c;Shopee平台对于使用同一IP地址同时登…

DevEco Studio在预览器上快速定位元素所在的组件代码位置

常规开发过程中 如果我们的组件过多 找对象就会比较困难 我们可以点击如下图指向位置 这边呢 就有一个组件树 我们可以快速定位到当前元素的代码位置 同时你在点元素的时候 代码它也给你标记出来了

仅2万粉,带了2.6万件的货!TikTok Shop美区达人周榜(11.13-11.19)

11月24日&#xff0c;TikTok Shop近日公布了美国市场和英国市场的全托管黑五大促战绩。数据显示&#xff0c;11月14日至11月20日&#xff0c;其美国市场的订单量环比10月20日-10月26日增长了205%。 家居户外热销品有&#xff1a;数码触摸屏相框、毛绒地毯、家居毛毯。黑马商品…

C语言基础篇5:指针(一)

指针是C语言的核心、精髓所在&#xff0c;用好了指针可以在C语言编程中起到事半功倍的效果。指针一方面可以提高程序的编译效率和执行速度&#xff0c;而且还可以通过指针实现动态的存储分配&#xff0c;另一方面使用指针可使程序更灵活&#xff0c;便于表示各种数据结构&#…

学习.NET验证模块FluentValidation的基本用法(续3:ASP.NET Core中的调用方式)

FluentValidation模块支持在ASP.NET Core项目中进行手工或自动验证&#xff0c;主要验证方式包括以下三种&#xff1a;   1&#xff09;手工注册验证类&#xff0c;并在控制器或其它模块中调用验证&#xff1b;   2&#xff09;基于ASP.NET验证管道&#xff08;validation …

CountDownLatch实战应用——批量数据多线程协调异步处理(主线程执行事务回滚)

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; CountDownLatch实战应用——批量数据多线程协调异步处理(主线程执行事务…

基于SpringBoot的超市信息管理系

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着我国经济的不断发…

送PDF书 | 豆瓣9.2分,超250万Python新手的选择!蟒蛇书入门到实践

在此疾速成长的科技元年&#xff0c;编程就像是许多人通往无限可能世界的门票。而在编程语言的明星阵容中&#xff0c;Python就像是那位独领风 骚的超级巨星&#xff0c; 以其简洁易懂的语法和强大的功能&#xff0c;脱颖而出&#xff0c;成为全球最炙手可热的编程语言之一。 …

【第二节:微信小程序 app.json配置】微信小程序入门,以思维导图的方式展开2

以思维导图的方式呈现出来&#xff0c;是不是会更加直观一些呢 如果看不清楚&#xff0c;私信给单发 &#xff1a; 第二节&#xff1a;微信小程序 app.json配置&#xff1a; 包括&#xff1a; window pages tabBar networkTimeout debug 如下图所示&#xff1a; 2、ap…

使用 OpenCV 发现圆角矩形的轮廓

OpenCV - 如何找到圆角矩形的矩形轮廓? 问题: 在图像中,我试图找到矩形对象的圆角轮廓。然而,我对两者的尝试 HoughLinesP 并 findContours 没有产生预期的结果。 我的目标是找到一个类似于以下形状的矩形: 。 代码: import cv2 import matplotlib.pyplot as plt…