首页 > 解决方案 > 如何在 docker 容器的 .net 核心应用程序中运行 python 脚本?

问题描述

我有一个 .Net 5 Core 应用程序,我正在将其转换为 docker 容器(linux 基础)。然而,这个应用程序调用 python 脚本来做一些计算。python 脚本需要 stix2 库,所以我首先进行初始设置以创建 virtualenv 并安装 stix2 库,如下所示:

  pip install virtualenv
  virtualenv virtual_env
  virtual_env\Scripts\activate
  pip install stix2
  deactivate

当调用 python 脚本时,它会读取一些 json,使用 stix2 库进行处理并将结果存储在同一文件夹中的另一个 json 文件中。python 脚本、输入、输出文件驻留在ContentRootPath.net 应用程序中。目前我正在使用SlavaGu控制台启动器从 .net 应用程序 (DoSomePythonProcess.cs) 中运行 python 脚本:

using SlavaGu.ConsoleAppLauncher;
.
.
.
string cmdLine = @"/c <contentrootpath>\Python\virtual_env\Scripts\activate "+
                         @"&& python " + <AbsolutePathToPythonScriptFile> + " " + <JSONInputFilePath> + " " + <JSONOutputFilePath> + @"&& <contentrootpath>\Python\virtual_env\Scripts\Scripts\deactivate";
ConsoleApp.Result result = ConsoleApp.Run("cmd", cmdLine);

现在,我正在尝试将此应用程序转换为 docker。目前,这是我的 dockerfile:

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
RUN apt-get update -y && apt-get install python3-pip python3 -y && pip3 install stix2
WORKDIR /app
EXPOSE 5070

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["project.Web.csproj", "project.Web/"]
RUN dotnet restore "project.Web.csproj"
COPY . .
WORKDIR "/src/project.Web"
RUN dotnet build "project.Web.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "project.Web.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ASPNETCORE_URLS=http://*:5070
ENTRYPOINT ["dotnet", "project.Web.dll"]

以下是我的问题:

如何为 python 脚本设置 virtualenv?可以在dockerfile中完成吗?

如何在这个 docker 容器中调用和执行 python 脚本?

此外,当我运行容器时,似乎无法识别 slavagu。如果是这种情况,我如何在 linux docker 容器中的 .net 应用程序中调用 python 脚本?

我在网上搜索过,但找不到任何相关的东西

任何帮助深表感谢!提前致谢!

##UPDATE## 感谢这里的建议,我能够找到解决方案。分享它,以防将来有人需要它:

dockerfile 没有变化。python 将安装在 /usr/bin/python3 下的容器中。which python3您可以在集装箱码头尝试“ ”来检查这一点。

关于如何在 .net 文件中调用 python 脚本:

install cliwrap nuget package

using CliWrap;
using CliWrap.Buffered;

#eg, to check where python is installed
var pathToPy = await Cli.Wrap("which")
      .WithArguments(new[] { "python3" })
      .ExecuteBufferedAsync();
var resOutput = pathToPy.StandardOutput;
_logger.LogInformation(resOutput);

标签: pythondockerasp.net-core

解决方案


在 python 容器中创建一个 virtualenv,在这个 venv 中安装依赖项并将其复制到您的应用程序容器中。

# prepare python env
FROM python:slim as python
# create a venv and install dependencies, use pip/poetry etc.
RUN python -m venv /venv
COPY requirements.txt .
# make sure you use the pip inside the venv
RUN /venv/bin/python -m pip install -r requirements.txt


# build your dotnet app
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
# ...


# build app container
FROM mcr.microsoft.com/dotnet/aspnet:5.0

COPY --from=build /app/publish .

# copy the python environment we've prepared
COPY --from=python /venv /python

# other configurations
# ...  
ENTRYPOINT ["dotnet", "project.Web.dll"]

然后,您可以/python/bin/python <args>从应用程序调用。依赖项将毫无问题地工作,因为它们将被 python 的默认搜索路径覆盖。

从 dotnet 运行 python 脚本

CliWrap在处理外部进程时使用 Alexey Golub 的库。

var result = await Cli.Wrap("/python/bin/python")
    .WithArguments(new []{"my_python_script.py", "arg1", "arg2"})
    .WithWorkingDirectory("/app/python_scripts")
    .ExecuteBufferedAsync();

var output = result.StandardOutput;
// do something with the output

推荐阅读