Как мне использовать файл .env для docker-compose vars в конфигурации для asp.net основное приложение?

#asp.net-core #docker-compose #environment-variables

#asp.net-core #docker-compose #переменные среды

Вопрос:

Я пытаюсь использовать файл .env, чтобы указать базовую строку подключения для моих контейнеров в docker compose. При запуске docker-compose config все выглядит хорошо, однако при запуске моего приложения строка подключения не включает переменную из .env файла.

Это пример моего .env :

 BASE_CONNECTION_STRING=Server=sqldb;userid=root;pwd=Pass@word;
  

и вот пример моего docker-compose:

   listings.api:
    environment:
      ASPNETCORE_ENVIRONMENT: Development
      ASPNETCORE_URLS: http:// :80
      ConnectionString: ${BASE_CONNECTION_STRING}Database=RentalListings.Services.ListingsDb;
  

Когда я запускаю docker-compose config , я получаю правильный результат, а именно:

 ConnectionString: Server=sqldb;userid=root;pwd=Pass@word;Database=RentalListings.Services.ListingsDb;
  

Однако, когда я запускаю свое приложение, я не получаю правильное значение. Запуск configuration["ConnectionString"] возвращает только Database=RentalListings.Services.ListingsDb;

Я попытался добавить .AddEnvironmentVariables(); в свой ConfigurationBuilder() , который добавлял переменные среды, которых раньше не было, когда я проверял конфигурацию ранее, но не добавлял те из .env файла. Независимо от того, я не уверен, должна ли эта часть иметь значение, поскольку я бы предположил, что эта переменная должна быть скомпилирована и передана docker независимо от моего ConfigurationBuilder .

Любая помощь была бы с благодарностью принята 🙂

ОБНОВЛЕНИЕ: вызов configuration["ConnectionString"] находится в моем ConfigureServices() в Startup.cs :

 public void ConfigureServices(IServiceCollection services)
        {
            services
                .AddCustomMVC(Configuration)
                .AddCustomDbContext(Configuration, _loggerFactory)
                .AddAppSettings(Configuration);
        }
  

с:

 public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration, ILoggerFactory loggerFactory)
        {
            ILogger<Startup> logger = loggerFactory.CreateLogger<Startup>();
            logger.LogInformation($"Conn string: {configuration["ConnectionString"]}");
            services.AddDbContext<ListingsContext>(options =>
            {
                options.UseMySql(configuration["ConnectionString"]);
                options.UseLoggerFactory(loggerFactory);
            });

            return services;
        }
  

Вот мой полный docker-compose.yml :

 version: '3.4'

services:
  sqldb:
    image: mariadb:latest

  listings.api:
    image: ${REGISTRY:-listings}/listings.api:${TAG:-latest}
    build:
      context: .
      dockerfile: src/Services/Listings/Listings.API/Dockerfile
    depends_on:
      - sqldb

  identity.api:
    image: ${REGISTRY:-identity}/identity.api:${TAG:-latest}
    build:
      context: .
      dockerfile: src/Services/Identity/Identity.API/Dockerfile
    depends_on:
      - sqldb

  webmvc:
    image: ${DOCKER:-listings}/webmvc:${TAG:-latest}
    build:
      context: .
      dockerfile: src/WebApps/WebMVC/Dockerfile
    depends_on:
      - listings.api
  

Вот мой docker-compose.override.yml :

 version: '3.4'

services:

  sqldb:
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - ACCEPT_EULA=Y
    ports:
      - "5433:1433"

  listings.api:
    environment:
      ASPNETCORE_ENVIRONMENT: Development
      ASPNETCORE_URLS: http:// :80
      ConnectionString: ${BASE_CONNECTION_STRING}Database=RentalListings.Services.ListingsDb;
    ports:
      - "57931:80"

  identity.api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http:// :80
      - ConnectionString=${BASE_CONNECTION_STRING}Database=RentalListings.Services.IdentityDb;
    ports:
      - "57932:80"

  webmvc:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http:// :80
      - ListingsAPIUrl=http://listings.api:80/api/v1
      - HomeUrl=http://localhost:55338
      - ListingsScope=${OIDC_SCOPES_LISTINGS}
      - ClientId=${OIDC_MVC_CLIENT_ID}
      - ClientSecret=${OIDC_MVC_CLIENT_SECRET}
    ports:
      - "55338:80"
  

И вот файл Dockerfile для списков.API

 FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY src/Services/Listings/Listings.API/Listings.API.csproj src/Services/Listings/Listings.API/
RUN dotnet restore src/Services/Listings/Listings.API/Listings.API.csproj
COPY . .
WORKDIR /src/src/Services/Listings/Listings.API
RUN dotnet build Listings.API.csproj -c Release -o /app

FROM build AS publish
RUN dotnet publish Listings.API.csproj -c Release -o /app

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

Комментарии:

1. можете ли вы опубликовать свой файл docker-compose.yml и любой файл Dockerfile, если вы его используете? Используете ли вы «ConnectionString» на этапах сборки или запуска? У меня такое чувство, что вы пытаетесь получить к нему доступ во время выполнения сборки docker-compose.

2. @Mihai добавил полные файлы docker-compose и dockerfiles. Также добавлен код, который получает строку подключения, которая находится в моем Startup.cs

3. При настройке у вас ошибка очень странная. У меня есть идея, и я предложу решение, но перед этим не могли бы вы ответить и на другой вопрос: ожидаете ли вы, что строка подключения будет заполнена в «docker-compose build» или в «docker-compose up»?

4. @Mihai Я не совсем уверен. Я использую Visual Studio для запуска приложения, которое (согласно этому сообщению: scrum-tips.com/2017/12/27 / … ), похоже, запускается docker-compose up -build

5. Не могли бы вы добавить это в качестве переменной среды рядом с ConnectionString в вашем docker-compose.override.yml: «- BASE_CONNECTION_STRING=${BASE_CONNECTION_STRING}». Добавьте его в обоих местах. Из того, как вы описываете проблему, «Строка подключения» каким-то образом вычисляется на сервере, а затем ищет BASE_CONNECTION_STRING. Что, согласно тому, что вы опубликовали здесь в качестве настройки, очень, очень странно. Итак, делая это, я работаю над этой теорией. Если это не сработает, нам нужно добавить больше отладочных сообщений, чтобы понять, что происходит. Дайте мне знать.

Ответ №1:

Если вы отлаживаете через Visual Studio (где docker-compose является проектом запуска), по умолчанию VS не загружает файл .env. Существует проблема, которая была закрыта, когда была рекомендация создать docker-compose.override.yml, который содержит ссылку на env_file

  env_file:
    - .env
  

Это сработает. Однако в моем случае я не хотел добавлять ссылку на файл .env в docker-compose.override.yml, поэтому я создал новый файл: docker-compose-debug.yml и я изменили docker-compose.dcproj, добавив узел AdditionalComposeFilePaths. composefilepaths. Мой docker-compose.dcproj теперь выглядит так:

 <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk" DefaultTargets="Build">
  <PropertyGroup Label="Globals">
    <ProjectVersion>2.1</ProjectVersion>
    <DockerTargetOS>Linux</DockerTargetOS>
    <ProjectGuid>a7290ad5-4ae3-4f88-9113-eed88eae9a32</ProjectGuid>
    <DockerLaunchAction>LaunchBrowser</DockerLaunchAction>
    <DockerServiceUrl>{Scheme}://localhost:{ServicePort}/swagger</DockerServiceUrl>
    <DockerServiceName>demo.api</DockerServiceName>
    <Configurations>Debug;Release</Configurations>
    <Platforms>AnyCPU</Platforms>
    <AdditionalComposeFilePaths>docker-compose-debug.yml</AdditionalComposeFilePaths>
  </PropertyGroup>
  <ItemGroup>
    <None Include="docker-compose.override.yml">
      <DependentUpon>docker-compose.yml</DependentUpon>
    </None>
    <None Include="docker-compose.yml" />
    <None Include=".dockerignore" />
  </ItemGroup>
</Project>