在 dotnet runtime 的容器中安装 dotnet global tool

在 dotnet runtime 的容器中安装 dotnet global tool

Intro

.NET Core 从 2.1 开始支持 Global tool, 借助 global tool 我们可以通过命令行来实现很多功能,微软提供的一系列的 dotnet 诊断工具也都提供了 global tool,我们可以通过 global tool 比较方便的进行使用,

但是 global tool 默认是只能装了 SDK 之后才能装,在实际的生产环境我们一般都是使用只包含 runtime 的 docker 镜像,没有 SDK 就不能直接安装 global tool,那我们要怎么做才能在只有 runtime 的 docker 镜像中使用 global tool 呢?且看下面的介绍

Global tool

dotnet global tool 是框架依赖发布的,所以是需要依赖运行时的,如果 dotnet tool 依赖的运行时找不到的时候,会尝试使用高版本的 runtime,遵循前滚(roll-forward)规则

  • 应用程序前滚至指定的主要版本和次要版本的最高修补程序版本。

  • 如果主要版本号和次要版本号没有匹配的运行时,则使用下一个较高的次要版本。

  • 前滚不会发生在 runtime 的预览版本,也不会发生在预览版和正式版之间。因此,使用预览版创建的 .NET  global tool 必须由作者重新生成和重新发布,再重新安装。

在下面两种常见的场景下默认不会发生 roll-forward :

  • 只有低版本运行时可用时,roll-forward 只会选择之后的版本,低版本不会被选择

  • 只有更高的主要版本运行时可用时,roll-forward 默认不会跨越主要版本的边界,主要版本发生变化有些 API 可能会有不兼容的变更

如果找不到一个合适的 runtime 版本,会运行失败并抛出错误信息。

我们可以通过 dotnet --info 或者 dotnet --list-runtimes 来查看已有的 runtime 信息

Install dotnet global tool

通过 dotnet tool install --global dotnet-dump 我们就可以安装 dotnet-dump 这个 global tool 了,但是就像前面提到的,我们必须要安装 SDK 才能安装 global tool,但是其实 global tool 运行的时候只依赖于 runtime,这就有点“悖论”了,明明我只需要 Runtime 就可以运行的,但是要安装 SDK 才能安装,在 Github 上提了一个 issue,有需要的可以关注一下:https://github.com/dotnet/sdk/issues/18168

在网上 Google 之后就会发现有一些解决方案,大体上分为两类,一种是直接安装 SDK 或使用 SDK 的环境,第二种则是在 SDK 的环境下安装 global tool,装好之后把 global tool 拷贝到只有 runtime 的环境中

Docker practice

在 docker 环境中,我们可以结合默认的多阶段构建的方案,在 build 镜像中安装 dotnet global tool,在最后拷贝发布内容的时候同时也拷贝 dotnet global tool

Dockerfile 示例如下:

FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build-env
WORKDIR /app

# install dotnet tool
RUN dotnet tool install --global dotnet-dump

COPY SparkTodo.Shared/SparkTodo.Shared.csproj SparkTodo.Shared/
COPY SparkTodo.API/SparkTodo.API.csproj SparkTodo.API/
RUN dotnet restore SparkTodo.API/SparkTodo.API.csproj

# copy everything and build
COPY . .

WORKDIR /app/SparkTodo.API
RUN dotnet publish -c Release -o out

# build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine
LABEL Maintainer="WeihanLi"
WORKDIR /app
COPY --from=build-env /app/SparkTodo.API/out .
COPY --from=build-env /root/.dotnet/tools /root/.dotnet/tools
ENV PATH="/root/.dotnet/tools:${PATH}"
EXPOSE 80
ENTRYPOINT ["dotnet", "SparkTodo.API.dll"]

通过多阶段构建的方式,我们可以避免直接使用特别大的 SDK 镜像,通过这种方式安装 dotnet tool 镜像只会增加几十M的大小(我装了一个 dotnet-dump,具体还是要看 dotnet tool 的大小)

通过 docker run --rm --name sparktodo sparktodo-api 运行一个容器,然后通过 docker exec -it sparktodo sh 进入到容器内部,然后就可以测试我们安装的 dotnet global tool 了

可以看到我们安装的 dotnet global tool 已经可以正常使用了

More

我们在 Dockerfile 里安装了 dotnet global tool 并使用了默认的 dotnet tool 的路径,并配置了环境变量以便于可以直接使用 dotnet global tool,如果需要也可以配置 dotnet tool 的安装路径,通过 dotnet tool install --global dotnet-dump --tool-path /usr/bin 来指定自定义的路径

References

  • https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools

  • https://docs.microsoft.com/en-us/dotnet/core/tools/troubleshoot-usage-issues

  • https://docs.microsoft.com/en-us/dotnet/core/deploying/#publish-framework-dependent

  • https://andrewlock.net/running-net-core-global-tools-in-non-sdk-docker-images/

  • https://github.com/dotnet/sdk/issues/18168

  • https://github.com/WeihanLi/SparkTodo/blob/master/Dockerfile

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值