【问题标题】:NLog config set connection string from docker run argumentNLog config 设置来自 docker run 参数的连接字符串
【发布时间】:2020-08-03 11:39:02
【问题描述】:

我有一个需要在 Docker 容器中运行的 .NET Core api 项目。该项目使用 NLog 将数据记录到数据库中。我想在运行容器时在 nlog.config 文件中设置连接字符串属性。

应用程序将部署到不同的客户端,并将使用它们的数据库进行日志记录。

这就是我尝试在 nlog.config 文件中配置连接字符串的方式:

...
  <target name="database" xsi:type="Database">
      <connectionString>'${environment:logs_connection_string}'</connectionString>
      <dbProvider>MySql.Data.MySqlClient.MySqlConnection, MySql.Data</dbProvider>
...

这是我的 Dockerfile:

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["Service/Service.csproj", "Service/"]
COPY ["Extensions/CustomExtensions.csproj", "Extensions/"]
RUN dotnet restore "Service/Service.csproj"
COPY . .
WORKDIR "/src/Service"
RUN dotnet build "Service.csproj" -c Release -o /app/build

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

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Service.dll"]
ARG log_connection
ENV logs_connection_string=$log_connection

这些是我在运行时传递连接字符串的一些尝试:

  • docker run -e log_connection="connection_string" -itd -p 1234:80 --name service service
  • docker run -e log_connection_string="connection_string" -itd -p 1234:80 --name service service

我没有太多使用 Docker 的经验,所以这种方法甚至可能不可行。我愿意接受任何建议。

【问题讨论】:

标签: docker asp.net-core nlog


【解决方案1】:

ARGENV 都不适合您想要完成的任务。

您需要的是某种入口点脚本,它将读取您在运行命令中设置的环境变量(在您的示例中为 log_connectionlog_connection_string),如果出现错误或将其设置为默认值它没有设置,最后编辑nlog.config并将&lt;connectionString&gt;的值设置为变量的值,最后运行dotnet Service.dll

例如,您可以像这样在nlog.config 中设置您的连接:

<connectionString>log_connection_string</connectionString>

然后创建文件run.ps1,内容如下:

#!/opt/microsoft/powershell/7/pwsh
if (-not (Test-Path env:log_connection_string)) { $env:log_connection_string = 'default value for log_connection_string' }
((Get-Content -Path path\to\nlog.config -Raw) -replace 'log_connection_string',$Env:log_connection_string) | Set-Content -Path path\to\nlog.config
dotnet Service.dll

在镜像构建期间将其复制到目录/app

并将 Dockerfile 的最后三行替换为:

ENTRYPOINT ["./run.ps1"]

编辑: 要在基础映像中安装 Powershell Core,请在 Dockerfile 中使用以下命令(最好在 FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base 下方):

RUN curl https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb --output packages-microsoft-prod.deb --silent && \
dpkg -i packages-microsoft-prod.deb && \
rm packages-microsoft-prod.deb && \
apt-get update && \
apt-get install -y powershell && \
apt-get clean

您还需要使run.ps1 可执行或将入口点更改为:

ENTRYPOINT ["/opt/microsoft/powershell/7/pwsh", "-Command","./run.ps1`enter code here`"] 

或者,您可以在 Bash 中使用等效脚本(我们将其命名为 run.sh):

#!/bin/bash
[[ -z "$log_connection_string" ]] && export log_connection_string="default value for log_connection_string"
sed -i 's/log_connection_string/'"$log_connection_string"'/' path\to\nlog.config
dotnet Service.dll

并且入口点应该设置为:

ENTRYPOINT ["/bin/bash", "-c", "./run.sh"]

最后一点:没有任何法律禁止使用小写的环境变量名称,但普遍接受的约定是全部大写,例如。 LOG_CONNECTION_STRING 而不是 log_connection_string

【讨论】:

  • 我忘了提一点,docker镜像是为linux主机环境编译的。 powershell 部分会在那种情况下运行吗?
  • 如果图像安装了 PowerShell(是的,PS 有 Linux 版本),它应该,虽然我认为你需要将 ENTRYPOINT 更改为 ["/path/to/pwsh", "-Command", "./run.ps1"]。如果不是,您将不得不在映像中安装它(有关详细信息,请参阅github.com/PowerShell/PowerShell),或者在映像中安装的任何 shell 中编写类似的脚本。
  • 感谢您的帮助。我有几天不在办公室。我回来后会检查解决方案。
【解决方案2】:

@Konrad Botor 的答案是可行的,因为他提供了一个非常好的答案,但是对于我的用例,有一种更简单的方法。 @RolfKristensen 的评论为我指明了正确的方向。

默认情况下,ASP.NET Core 应用程序会加载环境变量(请参阅 SO 上的此答案:Using AddEnvironmentVariables in .net core 3.1 app)。运行镜像时传递的环境变量,可以在应用中使用:

Environment.GetEnvironmentVariable("env_name").

正如@RolfKristensen 所提到的,NLog 知道如何加载环境变量。 nlog.config 文件中的连接字符串标记如下所示:

&lt;connectionString&gt;${environment:CONNECTION_STRING}&lt;/connectionString&gt;

运行命令如下所示。

docker run -itd -p 1234:80 --name test -e CONNECTION_STRING="..." app

连接字符串将从运行时传递的变量中正确加载。

对于传递敏感数据,这种方法存在安全风险,因为 docker run 命令将保留在命令历史记录中。但是有人可以使用 composer 文件或将主机的环境变量传递给 run 命令来降低风险。

编辑

我使用 Visual Studio 生成的 Dockerfile。

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["Service/Service.csproj", "Service/"]
COPY ["Extensions/CustomExtensions.csproj", "Extensions/"]
RUN dotnet restore "Service/Service.csproj"
COPY . .
WORKDIR "/src/Service"
RUN dotnet build "Service.csproj" -c Release -o /app/build

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 2022-08-18
    相关资源
    最近更新 更多