【问题标题】:Docker compose not picking up env variablesDocker compose 不拾取环境变量
【发布时间】:2021-02-06 14:27:34
【问题描述】:

我有一个包含 2 个微服务(产品和评论)的解决方案。 2 个 API 项目中的每一个都定义了一个 Dockerfile,这里是一个审查 dockerfile 的示例:

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

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src

ENV ConnectionString:Review="Data Source=db,1433;Initial Catalog=Review;uid=sa;pwd=TesT111t!;Integrated Security=false;MultipleActiveResultSets=True"

COPY ["Review.Api/Review.Api.csproj", "Review.Api/"]
COPY ["Review.Data/Review.Data.csproj", "Review.Data/"]
COPY ["Review.Service/Review.Service.csproj", "Review.Service/"]
RUN dotnet restore "Review.Api/Review.Api.csproj"
COPY . .
WORKDIR "/src/Review.Api"
RUN dotnet build "Review.Api.csproj" -c Release -o /app/build

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

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

如您所见,dockerfile 包含一个环境变量 ConnectionString

我在 review api 项目的启动中有一个断点来检查 Configuration 里面的内容,这是文件的样子:

public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ReviewDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Review")), ServiceLifetime.Transient);
        services.AddAutoMapper(typeof(FindProductReviews));
        services.AddAutoMapper(typeof(FindReview));
        services.AddAutoMapper(typeof(ReviewController));
        services.AddAutoMapper(typeof(ProductController));
        services.AddMediatR(typeof(FindProductReviews.Handler).Assembly);
        services.AddMediatR(typeof(FindReview.Handler).Assembly);
        services.AddMediatR(typeof(CreateReview.Handler).Assembly);
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapDefaultControllerRoute();
        });
    }
}

我的解决方案有一个docker-compose 文件,在运行docker-compose up -d 时会遇到断点,但是在查看Configuration 内部时,它们没有像dockerfile 中那样定义的连接字符串。

我觉得我错过了一些小东西,我查看了文档但找不到我错过的东西

【问题讨论】:

  • Linux 环境变量名称必须使用双下划线部分分隔符,而不是冒号

标签: c# docker .net-core docker-compose


【解决方案1】:

应用初始配置

首先,请确认,当您的程序启动时,您正在构建如下配置(典型设置),以便将其与 env.variables 绑定。

// Defining a configuration that explicitly uses env. variables
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
            ...
            .AddEnvironmentVariables()
            .Build();

// The default builder already adds env. variables
public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            ...

码头工人

请将ConnectionString:Review 替换为ConnectionString__Review(参考here)。

如果你想继续设置Dockerfile中的env.variable,你可以把它移到最后一个部分final,例如:

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ConnectionString__Review="Data Source=db,1433;Initial Catalog=Review;uid=sa;pwd=TesT111t!;Integrated Security=false;MultipleActiveResultSets=True"
ENTRYPOINT ["dotnet", "Review.Api.dll"]

但是,为了增强解耦,您可能更愿意在 docker-compose 文件中设置变量。

您也可以考虑使用appsettings JSON 文件,因为它们允许跨环境的灵活性很大。

多种连接配置

如果您的服务能够访问共享配置,但也有自己的,那么,您可以为每个配置指定正确的名称,以确保发生任何错误:)

【讨论】:

  • 我已经把它放在 final 之后但仍然没有得到 env 变量?
  • 对不起,为了清楚起见,我编辑了答案,请看看它是否合适。我和我的同事在一些项目中做类似的事情
  • 由于某种原因我仍然没有得到它?挺奇怪的,我试试再加个env变量看看有没有收到
  • 我没有注意到:。请尝试仅包含字母数字字符的变量(_ 也接受)
  • 我会再次编辑,抱歉,没注意到。请将: 替换为双下划线__。参考是here
【解决方案2】:

您只需在build 图像中定义ENV 变量。如果您遵循FROM 链,则final 映像将构建FROM baseCOPY --from=build,但COPY 仅复制文件,而不复制环境变量或其他元数据。

您的问题标题和标签暗示了基于 Compose 的设置。需要在部署时配置连接信息,例如数据库主机名和(尤其是)凭据,而不是映像的一部分。我会从您的Dockerfile 中完全删除这一行,并将其包含在您的docker-compose.yml 中:

version: '3.8'
services:
  db: { ... }
  app:
    environment:
      - ConnectionString:Review=Data Source=db,1433;Initial Catalog=Review;uid=sa;pwd=TesT111t!;Integrated Security=false;MultipleActiveResultSets=True
    ...

【讨论】:

  • 我明白了,但是我如何定义多个连接字符串,因为我有多个服务(产品和评论)
  • 在 Compose 文件中,您可以为每个服务声明一个单独的数据库和一个相应的连接字符串,如果您需要的话。
猜你喜欢
  • 2020-07-16
  • 2015-06-17
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 2017-06-16
  • 2022-01-01
  • 2018-02-03
  • 2019-02-25
相关资源
最近更新 更多